<COMMENT>/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/
</COMMENT><IMPORT_STATEMENT>
import { $ } from '../../../../base/browser/dom.js';
</IMPORT_STATEMENT><IMPORT_STATEMENT-1>import { Dialog } from '../../../../base/browser/ui/dialog/dialog.js';
</IMPORT_STATEMENT-1><IMPORT_STATEMENT-2>import { toAction, WorkbenchActionExecutedClassification, WorkbenchActionExecutedEvent } from '../../../../base/common/actions.js';
</IMPORT_STATEMENT-2><IMPORT_STATEMENT-3>import { timeout } from '../../../../base/common/async.js';
</IMPORT_STATEMENT-3><IMPORT_STATEMENT-4>import { CancellationToken } from '../../../../base/common/cancellation.js';
</IMPORT_STATEMENT-4><IMPORT_STATEMENT-5>import { Codicon } from '../../../../base/common/codicons.js';
</IMPORT_STATEMENT-5><IMPORT_STATEMENT-6>import { toErrorMessage } from '../../../../base/common/errorMessage.js';
</IMPORT_STATEMENT-6><IMPORT_STATEMENT-7>import { isCancellationError } from '../../../../base/common/errors.js';
</IMPORT_STATEMENT-7><IMPORT_STATEMENT-8>import { Emitter, Event } from '../../../../base/common/event.js';
</IMPORT_STATEMENT-8><IMPORT_STATEMENT-9>import { MarkdownString } from '../../../../base/common/htmlContent.js';
</IMPORT_STATEMENT-9><IMPORT_STATEMENT-10>import { Lazy } from '../../../../base/common/lazy.js';
</IMPORT_STATEMENT-10><IMPORT_STATEMENT-11>import { Disposable, DisposableStore, IDisposable, markAsSingleton, MutableDisposable } from '../../../../base/common/lifecycle.js';
</IMPORT_STATEMENT-11><IMPORT_STATEMENT-12>import Severity from '../../../../base/common/severity.js';
</IMPORT_STATEMENT-12><IMPORT_STATEMENT-13>import { StopWatch } from '../../../../base/common/stopwatch.js';
</IMPORT_STATEMENT-13><IMPORT_STATEMENT-14>import { equalsIgnoreCase } from '../../../../base/common/strings.js';
</IMPORT_STATEMENT-14><IMPORT_STATEMENT-15>import { isObject } from '../../../../base/common/types.js';
</IMPORT_STATEMENT-15><IMPORT_STATEMENT-16>import { URI } from '../../../../base/common/uri.js';
</IMPORT_STATEMENT-16><IMPORT_STATEMENT-17>import { ServicesAccessor } from '../../../../editor/browser/editorExtensions.js';
</IMPORT_STATEMENT-17><IMPORT_STATEMENT-18>import { MarkdownRenderer } from '../../../../editor/browser/widget/markdownRenderer/browser/markdownRenderer.js';
</IMPORT_STATEMENT-18><IMPORT_STATEMENT-19>import { localize, localize2 } from '../../../../nls.js';
</IMPORT_STATEMENT-19><IMPORT_STATEMENT-20>import { Action2, MenuId, registerAction2 } from '../../../../platform/actions/common/actions.js';
</IMPORT_STATEMENT-20><IMPORT_STATEMENT-21>import { ICommandService } from '../../../../platform/commands/common/commands.js';
</IMPORT_STATEMENT-21><IMPORT_STATEMENT-22>import { ConfigurationTarget, IConfigurationService } from '../../../../platform/configuration/common/configuration.js';
</IMPORT_STATEMENT-22><IMPORT_STATEMENT-23>import { Extensions as ConfigurationExtensions, IConfigurationRegistry } from '../../../../platform/configuration/common/configurationRegistry.js';
</IMPORT_STATEMENT-23><IMPORT_STATEMENT-24>import { ContextKeyExpr } from '../../../../platform/contextkey/common/contextkey.js';
</IMPORT_STATEMENT-24><IMPORT_STATEMENT-25>import { IContextMenuService } from '../../../../platform/contextview/browser/contextView.js';
</IMPORT_STATEMENT-25><IMPORT_STATEMENT-26>import { createWorkbenchDialogOptions } from '../../../../platform/dialogs/browser/dialog.js';
</IMPORT_STATEMENT-26><IMPORT_STATEMENT-27>import { IDialogService } from '../../../../platform/dialogs/common/dialogs.js';
</IMPORT_STATEMENT-27><IMPORT_STATEMENT-28>import { IInstantiationService } from '../../../../platform/instantiation/common/instantiation.js';
</IMPORT_STATEMENT-28><IMPORT_STATEMENT-29>import { IKeybindingService } from '../../../../platform/keybinding/common/keybinding.js';
</IMPORT_STATEMENT-29><IMPORT_STATEMENT-30>import { ILayoutService } from '../../../../platform/layout/browser/layoutService.js';
</IMPORT_STATEMENT-30><IMPORT_STATEMENT-31>import { ILogService } from '../../../../platform/log/common/log.js';
</IMPORT_STATEMENT-31><IMPORT_STATEMENT-32>import { IOpenerService } from '../../../../platform/opener/common/opener.js';
</IMPORT_STATEMENT-32><IMPORT_STATEMENT-33>import product from '../../../../platform/product/common/product.js';
</IMPORT_STATEMENT-33><IMPORT_STATEMENT-34>import { IProductService } from '../../../../platform/product/common/productService.js';
</IMPORT_STATEMENT-34><IMPORT_STATEMENT-35>import { IProgressService, ProgressLocation } from '../../../../platform/progress/common/progress.js';
</IMPORT_STATEMENT-35><IMPORT_STATEMENT-36>import { IQuickInputService } from '../../../../platform/quickinput/common/quickInput.js';
</IMPORT_STATEMENT-36><IMPORT_STATEMENT-37>import { Registry } from '../../../../platform/registry/common/platform.js';
</IMPORT_STATEMENT-37><IMPORT_STATEMENT-38>import { ITelemetryService, TelemetryLevel } from '../../../../platform/telemetry/common/telemetry.js';
</IMPORT_STATEMENT-38><IMPORT_STATEMENT-39>import { IWorkspaceTrustRequestService } from '../../../../platform/workspace/common/workspaceTrust.js';
</IMPORT_STATEMENT-39><IMPORT_STATEMENT-40>import { IWorkbenchContribution } from '../../../common/contributions.js';
</IMPORT_STATEMENT-40><IMPORT_STATEMENT-41>import { IViewDescriptorService, ViewContainerLocation } from '../../../common/views.js';
</IMPORT_STATEMENT-41><IMPORT_STATEMENT-42>import { IActivityService, ProgressBadge } from '../../../services/activity/common/activity.js';
</IMPORT_STATEMENT-42><IMPORT_STATEMENT-43>import { AuthenticationSession, IAuthenticationService } from '../../../services/authentication/common/authentication.js';
</IMPORT_STATEMENT-43><IMPORT_STATEMENT-44>import { ExtensionUrlHandlerOverrideRegistry } from '../../../services/extensions/browser/extensionUrlHandler.js';
</IMPORT_STATEMENT-44><IMPORT_STATEMENT-45>import { nullExtensionDescription } from '../../../services/extensions/common/extensions.js';
</IMPORT_STATEMENT-45><IMPORT_STATEMENT-46>import { IHostService } from '../../../services/host/browser/host.js';
</IMPORT_STATEMENT-46><IMPORT_STATEMENT-47>import { IWorkbenchLayoutService, Parts } from '../../../services/layout/browser/layoutService.js';
</IMPORT_STATEMENT-47><IMPORT_STATEMENT-48>import { ILifecycleService } from '../../../services/lifecycle/common/lifecycle.js';
</IMPORT_STATEMENT-48><IMPORT_STATEMENT-49>import { IViewsService } from '../../../services/views/common/viewsService.js';
</IMPORT_STATEMENT-49><IMPORT_STATEMENT-50>import { CountTokensCallback, ILanguageModelToolsService, IPreparedToolInvocation, IToolData, IToolImpl, IToolInvocation, IToolResult } from '../../chat/common/languageModelToolsService.js';
</IMPORT_STATEMENT-50><IMPORT_STATEMENT-51>import { IExtensionsWorkbenchService } from '../../extensions/common/extensions.js';
</IMPORT_STATEMENT-51><IMPORT_STATEMENT-52>import { IChatAgentImplementation, IChatAgentRequest, IChatAgentResult, IChatAgentService } from '../common/chatAgents.js';
</IMPORT_STATEMENT-52><IMPORT_STATEMENT-53>import { ChatContextKeys } from '../common/chatContextKeys.js';
</IMPORT_STATEMENT-53><IMPORT_STATEMENT-54>import { ChatEntitlement, ChatEntitlementContext, ChatEntitlementRequests, ChatEntitlementService, IChatEntitlementService } from '../common/chatEntitlementService.js';
</IMPORT_STATEMENT-54><IMPORT_STATEMENT-55>import { ChatModel, ChatRequestModel, IChatRequestModel, IChatRequestToolEntry, IChatRequestVariableData } from '../common/chatModel.js';
</IMPORT_STATEMENT-55><IMPORT_STATEMENT-56>import { ChatRequestAgentPart, ChatRequestToolPart } from '../common/chatParserTypes.js';
</IMPORT_STATEMENT-56><IMPORT_STATEMENT-57>import { IChatProgress, IChatService } from '../common/chatService.js';
</IMPORT_STATEMENT-57><IMPORT_STATEMENT-58>import { ChatAgentLocation, ChatConfiguration, ChatMode, validateChatMode } from '../common/constants.js';
</IMPORT_STATEMENT-58><IMPORT_STATEMENT-59>import { ILanguageModelsService } from '../common/languageModels.js';
</IMPORT_STATEMENT-59><IMPORT_STATEMENT-60>import { CHAT_CATEGORY, CHAT_OPEN_ACTION_ID, CHAT_SETUP_ACTION_ID } from './actions/chatActions.js';
</IMPORT_STATEMENT-60><IMPORT_STATEMENT-61>import { ChatViewId, IChatWidgetService, showCopilotView } from './chat.js';
</IMPORT_STATEMENT-61><IMPORT_STATEMENT-62>import { CHAT_SIDEBAR_PANEL_ID } from './chatViewPane.js';
</IMPORT_STATEMENT-62><IMPORT_STATEMENT-63>import './media/chatSetup.css';
</IMPORT_STATEMENT-63><LEXICAL_DECLARATION>
const defaultChat = {
	extensionId: product.defaultChatAgent?.extensionId ?? '',
	chatExtensionId: product.defaultChatAgent?.chatExtensionId ?? '',
	documentationUrl: product.defaultChatAgent?.documentationUrl ?? '',
	termsStatementUrl: product.defaultChatAgent?.termsStatementUrl ?? '',
	privacyStatementUrl: product.defaultChatAgent?.privacyStatementUrl ?? '',
	skusDocumentationUrl: product.defaultChatAgent?.skusDocumentationUrl ?? '',
	publicCodeMatchesUrl: product.defaultChatAgent?.publicCodeMatchesUrl ?? '',
	upgradePlanUrl: product.defaultChatAgent?.upgradePlanUrl ?? '',
	providerName: product.defaultChatAgent?.providerName ?? '',
	enterpriseProviderId: product.defaultChatAgent?.enterpriseProviderId ?? '',
	enterpriseProviderName: product.defaultChatAgent?.enterpriseProviderName ?? '',
	providerUriSetting: product.defaultChatAgent?.providerUriSetting ?? '',
	providerScopes: product.defaultChatAgent?.providerScopes ?? [[]],
	manageSettingsUrl: product.defaultChatAgent?.manageSettingsUrl ?? '',
	completionsAdvancedSetting: product.defaultChatAgent?.completionsAdvancedSetting ?? '',
	walkthroughCommand: product.defaultChatAgent?.walkthroughCommand ?? '',
	completionsRefreshTokenCommand: product.defaultChatAgent?.completionsRefreshTokenCommand ?? '',
	chatRefreshTokenCommand: product.defaultChatAgent?.chatRefreshTokenCommand ?? '',
};
</LEXICAL_DECLARATION><COMMENT-1>
//#region Contribution
</COMMENT-1><LEXICAL_DECLARATION-1>
const ToolsAgentWhen = ContextKeyExpr.and(
	ContextKeyExpr.equals(`config.${ChatConfiguration.AgentEnabled}`, true),
	ChatContextKeys.Editing.agentModeDisallowed.negate(),
	ContextKeyExpr.not(`previewFeaturesDisabled`)<COMMENT-2> // Set by extension
</COMMENT-2>);
</LEXICAL_DECLARATION-1><CLASS_DECLARATION>
class SetupChatAgent extends Disposable implements IChatAgentImplementation {
<METHOD_DEFINITION>
	static registerDefaultAgents(instantiationService: IInstantiationService, location: ChatAgentLocation, mode: ChatMode | undefined, context: ChatEntitlementContext, controller: Lazy<ChatSetupController>): { disposable: IDisposable; agent: SetupChatAgent } {
<RETURN_STATEMENT>		return instantiationService.invokeFunction(accessor => {
<LEXICAL_DECLARATION-2>			const chatAgentService = accessor.get(IChatAgentService);
</LEXICAL_DECLARATION-2><LEXICAL_DECLARATION-3>
			let id: string;
</LEXICAL_DECLARATION-3><LEXICAL_DECLARATION-4>			let description = localize('chatDescription', "Ask Copilot");
</LEXICAL_DECLARATION-4><SWITCH_STATEMENT>			switch (location) {
<SWITCH_CASE>				case ChatAgentLocation.Panel:
<IF_STATEMENT>					if (mode === ChatMode.Ask) {
<EXPRESSION_STATEMENT>						id = 'setup.chat';
</EXPRESSION_STATEMENT>					} else if (mode === ChatMode.Edit) {
<EXPRESSION_STATEMENT-1>						id = 'setup.edits';
</EXPRESSION_STATEMENT-1><EXPRESSION_STATEMENT-2>						description = localize('editsDescription', "Edit files in your workspace");
</EXPRESSION_STATEMENT-2>					} else {
<EXPRESSION_STATEMENT-3>						id = 'setup.agent';
</EXPRESSION_STATEMENT-3><EXPRESSION_STATEMENT-4>						description = localize('agentDescription', "Edit files in your workspace in agent mode");
</EXPRESSION_STATEMENT-4>					}
</IF_STATEMENT><BREAK_STATEMENT>					break;</BREAK_STATEMENT>
</SWITCH_CASE><SWITCH_CASE-1>				case ChatAgentLocation.Terminal:
<EXPRESSION_STATEMENT-5>					id = 'setup.terminal';
</EXPRESSION_STATEMENT-5><BREAK_STATEMENT-1>					break;</BREAK_STATEMENT-1>
</SWITCH_CASE-1><SWITCH_CASE-2>				case ChatAgentLocation.Editor:
<EXPRESSION_STATEMENT-6>					id = 'setup.editor';
</EXPRESSION_STATEMENT-6><BREAK_STATEMENT-2>					break;</BREAK_STATEMENT-2>
</SWITCH_CASE-2><SWITCH_CASE-3>				case ChatAgentLocation.Notebook:
<EXPRESSION_STATEMENT-7>					id = 'setup.notebook';
</EXPRESSION_STATEMENT-7><BREAK_STATEMENT-3>					break;</BREAK_STATEMENT-3>
</SWITCH_CASE-3>			}
</SWITCH_STATEMENT><RETURN_STATEMENT-1>
			return SetupChatAgent.registerAgents(instantiationService, chatAgentService, id, `${defaultChat.providerName} Copilot`, true, description, location, mode, context, controller);
</RETURN_STATEMENT-1>		});
</RETURN_STATEMENT>	}
</METHOD_DEFINITION><METHOD_DEFINITION-1>
	static registerOtherAgents(instantiationService: IInstantiationService, id: string, name: string, isDefault: boolean, description: string, location: ChatAgentLocation, mode: ChatMode | undefined, context: ChatEntitlementContext, controller: Lazy<ChatSetupController>): { disposable: IDisposable; agent: SetupChatAgent } {
<RETURN_STATEMENT-2>		return instantiationService.invokeFunction(accessor => {
<LEXICAL_DECLARATION-5>			const chatAgentService = accessor.get(IChatAgentService);
</LEXICAL_DECLARATION-5><RETURN_STATEMENT-3>			return SetupChatAgent.registerAgents(instantiationService, chatAgentService, id, name, isDefault, description, location, mode, context, controller);
</RETURN_STATEMENT-3>		});
</RETURN_STATEMENT-2>	}
</METHOD_DEFINITION-1><METHOD_DEFINITION-2>
	static registerAgents(instantiationService: IInstantiationService, chatAgentService: IChatAgentService, id: string, name: string, isDefault: boolean, description: string, location: ChatAgentLocation, mode: ChatMode | undefined, context: ChatEntitlementContext, controller: Lazy<ChatSetupController>): { disposable: IDisposable; agent: SetupChatAgent } {
<LEXICAL_DECLARATION-6>
		const disposables = new DisposableStore();
</LEXICAL_DECLARATION-6><EXPRESSION_STATEMENT-8>		disposables.add(chatAgentService.registerAgent(id, {
			id,
			name,
			isDefault,
			isCore: true,
			modes: mode ? [mode] : [ChatMode.Ask],
			when: mode === ChatMode.Agent ? ToolsAgentWhen?.serialize() : undefined,
			slashCommands: [],
			disambiguation: [],
			locations: [location],
			metadata: { helpTextPrefix: SetupChatAgent.SETUP_NEEDED_MESSAGE },
			description,
			extensionId: nullExtensionDescription.identifier,
			extensionDisplayName: nullExtensionDescription.name,
			extensionPublisherId: nullExtensionDescription.publisher
		}));
</EXPRESSION_STATEMENT-8><LEXICAL_DECLARATION-7>
		const agent = disposables.add(instantiationService.createInstance(SetupChatAgent, context, controller, location));
</LEXICAL_DECLARATION-7><EXPRESSION_STATEMENT-9>		disposables.add(chatAgentService.registerAgentImplementation(id, agent));
</EXPRESSION_STATEMENT-9><RETURN_STATEMENT-4>
		return { agent, disposable: disposables };
</RETURN_STATEMENT-4>	}
</METHOD_DEFINITION-2><PUBLIC_FIELD_DEFINITION>
	private static readonly SETUP_NEEDED_MESSAGE = new MarkdownString(localize('settingUpCopilotNeeded', "You need to set up Copilot to use Chat."));
</PUBLIC_FIELD_DEFINITION><PUBLIC_FIELD_DEFINITION-1>
	private readonly _onUnresolvableError = this._register(new Emitter<void>());
</PUBLIC_FIELD_DEFINITION-1><PUBLIC_FIELD_DEFINITION-2>	readonly onUnresolvableError = this._onUnresolvableError.event;
</PUBLIC_FIELD_DEFINITION-2><PUBLIC_FIELD_DEFINITION-3>
	private readonly pendingForwardedRequests = new Map<string, Promise<void>>();
</PUBLIC_FIELD_DEFINITION-3><CONSTRUCTOR>
	constructor(
		private readonly context: ChatEntitlementContext,
		private readonly controller: Lazy<ChatSetupController>,
		private readonly location: ChatAgentLocation,
		@IInstantiationService private readonly instantiationService: IInstantiationService,
		@ILogService private readonly logService: ILogService,
		@IConfigurationService private readonly configurationService: IConfigurationService,
		@ITelemetryService private readonly telemetryService: ITelemetryService,
	) {
<EXPRESSION_STATEMENT-10>		super();
</EXPRESSION_STATEMENT-10>	}
</CONSTRUCTOR><METHOD_DEFINITION-3>
	async invoke(request: IChatAgentRequest, progress: (part: IChatProgress) => void): Promise<IChatAgentResult> {
<RETURN_STATEMENT-5>		return this.instantiationService.invokeFunction(async accessor<COMMENT-3> /* using accessor for lazy loading */</COMMENT-3> => {
<LEXICAL_DECLARATION-8>			const chatService = accessor.get(IChatService);
</LEXICAL_DECLARATION-8><LEXICAL_DECLARATION-9>			const languageModelsService = accessor.get(ILanguageModelsService);
</LEXICAL_DECLARATION-9><LEXICAL_DECLARATION-10>			const chatWidgetService = accessor.get(IChatWidgetService);
</LEXICAL_DECLARATION-10><LEXICAL_DECLARATION-11>			const chatAgentService = accessor.get(IChatAgentService);
</LEXICAL_DECLARATION-11><LEXICAL_DECLARATION-12>			const languageModelToolsService = accessor.get(ILanguageModelToolsService);
</LEXICAL_DECLARATION-12><RETURN_STATEMENT-6>			return this.doInvoke(request, progress, chatService, languageModelsService, chatWidgetService, chatAgentService, languageModelToolsService);
</RETURN_STATEMENT-6>		});
</RETURN_STATEMENT-5>	}
</METHOD_DEFINITION-3><METHOD_DEFINITION-4>
	private async doInvoke(request: IChatAgentRequest, progress: (part: IChatProgress) => void, chatService: IChatService, languageModelsService: ILanguageModelsService, chatWidgetService: IChatWidgetService, chatAgentService: IChatAgentService, languageModelToolsService: ILanguageModelToolsService): Promise<IChatAgentResult> {
<IF_STATEMENT-1>		if (!this.context.state.installed || this.context.state.entitlement === ChatEntitlement.Available || this.context.state.entitlement === ChatEntitlement.Unknown) {
<RETURN_STATEMENT-7>			return this.doInvokeWithSetup(request, progress, chatService, languageModelsService, chatWidgetService, chatAgentService, languageModelToolsService);
</RETURN_STATEMENT-7>		}
</IF_STATEMENT-1><RETURN_STATEMENT-8>
		return this.doInvokeWithoutSetup(request, progress, chatService, languageModelsService, chatWidgetService, chatAgentService, languageModelToolsService);
</RETURN_STATEMENT-8>	}
</METHOD_DEFINITION-4><METHOD_DEFINITION-5>
	private async doInvokeWithoutSetup(request: IChatAgentRequest, progress: (part: IChatProgress) => void, chatService: IChatService, languageModelsService: ILanguageModelsService, chatWidgetService: IChatWidgetService, chatAgentService: IChatAgentService, languageModelToolsService: ILanguageModelToolsService): Promise<IChatAgentResult> {
<LEXICAL_DECLARATION-13>		const requestModel = chatWidgetService.getWidgetBySessionId(request.sessionId)?.viewModel?.model.getRequests().at(-1);
</LEXICAL_DECLARATION-13><IF_STATEMENT-2>		if (!requestModel) {
<EXPRESSION_STATEMENT-11>			this.logService.error('[chat setup] Request model not found, cannot redispatch request.');
</EXPRESSION_STATEMENT-11><RETURN_STATEMENT-9>			return {}; // this should not happen
</RETURN_STATEMENT-9>		}
</IF_STATEMENT-2><EXPRESSION_STATEMENT-12>
		progress({
			kind: 'progressMessage',
			content: new MarkdownString(localize('waitingCopilot', "Getting Copilot ready.")),
		});
</EXPRESSION_STATEMENT-12><EXPRESSION_STATEMENT-13>
		await this.forwardRequestToCopilot(requestModel, progress, chatService, languageModelsService, chatAgentService, chatWidgetService, languageModelToolsService);
</EXPRESSION_STATEMENT-13><RETURN_STATEMENT-10>
		return {};
</RETURN_STATEMENT-10>	}
</METHOD_DEFINITION-5><METHOD_DEFINITION-6>
	private async forwardRequestToCopilot(requestModel: IChatRequestModel, progress: (part: IChatProgress) => void, chatService: IChatService, languageModelsService: ILanguageModelsService, chatAgentService: IChatAgentService, chatWidgetService: IChatWidgetService, languageModelToolsService: ILanguageModelToolsService): Promise<void> {
<TRY_STATEMENT>		try {
<EXPRESSION_STATEMENT-14>			await this.doForwardRequestToCopilot(requestModel, progress, chatService, languageModelsService, chatAgentService, chatWidgetService, languageModelToolsService);
</EXPRESSION_STATEMENT-14>		} catch (error) {
<EXPRESSION_STATEMENT-15>			progress({
				kind: 'warning',
				content: new MarkdownString(localize('copilotUnavailableWarning', "Copilot failed to get a response. Please try again."))
			});
</EXPRESSION_STATEMENT-15>		}
</TRY_STATEMENT>	}
</METHOD_DEFINITION-6><METHOD_DEFINITION-7>
	private async doForwardRequestToCopilot(requestModel: IChatRequestModel, progress: (part: IChatProgress) => void, chatService: IChatService, languageModelsService: ILanguageModelsService, chatAgentService: IChatAgentService, chatWidgetService: IChatWidgetService, languageModelToolsService: ILanguageModelToolsService): Promise<void> {
<IF_STATEMENT-3>		if (this.pendingForwardedRequests.has(requestModel.session.sessionId)) {
<THROW_STATEMENT>			throw new Error('Request already in progress');
</THROW_STATEMENT>		}
</IF_STATEMENT-3><LEXICAL_DECLARATION-14>
		const forwardRequest = this.doForwardRequestToCopilotWhenReady(requestModel, progress, chatService, languageModelsService, chatAgentService, chatWidgetService, languageModelToolsService);
</LEXICAL_DECLARATION-14><EXPRESSION_STATEMENT-16>		this.pendingForwardedRequests.set(requestModel.session.sessionId, forwardRequest);
</EXPRESSION_STATEMENT-16><TRY_STATEMENT-1>
		try {
<EXPRESSION_STATEMENT-17>			await forwardRequest;
</EXPRESSION_STATEMENT-17>		} finally {
<EXPRESSION_STATEMENT-18>			this.pendingForwardedRequests.delete(requestModel.session.sessionId);
</EXPRESSION_STATEMENT-18>		}
</TRY_STATEMENT-1>	}
</METHOD_DEFINITION-7><METHOD_DEFINITION-8>
	private async doForwardRequestToCopilotWhenReady(requestModel: IChatRequestModel, progress: (part: IChatProgress) => void, chatService: IChatService, languageModelsService: ILanguageModelsService, chatAgentService: IChatAgentService, chatWidgetService: IChatWidgetService, languageModelToolsService: ILanguageModelToolsService): Promise<void> {
<LEXICAL_DECLARATION-15>		const widget = chatWidgetService.getWidgetBySessionId(requestModel.session.sessionId);
</LEXICAL_DECLARATION-15><LEXICAL_DECLARATION-16>		const mode = widget?.input.currentMode;
</LEXICAL_DECLARATION-16><LEXICAL_DECLARATION-17>		const languageModel = widget?.input.currentLanguageModel;
</LEXICAL_DECLARATION-17><COMMENT-4>
		// We need a signal to know when we can resend the request to
</COMMENT-4><COMMENT-5>		// Copilot. Waiting for the registration of the agent is not
</COMMENT-5><COMMENT-6>		// enough, we also need a language model to be available.
</COMMENT-6><LEXICAL_DECLARATION-18>
		const whenLanguageModelReady = this.whenLanguageModelReady(languageModelsService);
</LEXICAL_DECLARATION-18><LEXICAL_DECLARATION-19>		const whenAgentReady = this.whenAgentReady(chatAgentService, mode);
</LEXICAL_DECLARATION-19><LEXICAL_DECLARATION-20>		const whenToolsModelReady = this.whenToolsModelReady(languageModelToolsService, requestModel);
</LEXICAL_DECLARATION-20><IF_STATEMENT-4>
		if (whenLanguageModelReady instanceof Promise || whenAgentReady instanceof Promise || whenToolsModelReady instanceof Promise) {
<LEXICAL_DECLARATION-21>			const timeoutHandle = setTimeout(() => {
<EXPRESSION_STATEMENT-19>				progress({
					kind: 'progressMessage',
					content: new MarkdownString(localize('waitingCopilot2', "Copilot is almost ready.")),
				});
</EXPRESSION_STATEMENT-19>			}, 10000);
</LEXICAL_DECLARATION-21><TRY_STATEMENT-2>
			try {
<LEXICAL_DECLARATION-22>				const ready = await Promise.race([
					timeout(20000).then(() => 'timedout'),
					this.whenDefaultAgentFailed(chatService).then(() => 'error'),
					Promise.allSettled([whenLanguageModelReady, whenAgentReady, whenToolsModelReady])
				]);
</LEXICAL_DECLARATION-22><IF_STATEMENT-5>
				if (ready === 'error' || ready === 'timedout') {
<EXPRESSION_STATEMENT-20>					progress({
						kind: 'warning',
						content: new MarkdownString(ready === 'timedout' ?
							localize('copilotTookLongWarning', "Copilot took too long to get ready. Please review the guidance in the Chat view.") :
							localize('copilotFailedWarning', "Copilot failed to get ready. Please review the guidance in the Chat view.")
						)
					});
</EXPRESSION_STATEMENT-20><COMMENT-7>
					// This means Copilot is unhealthy and we cannot retry the
</COMMENT-7><COMMENT-8>					// request. Signal this to the outside via an event.
</COMMENT-8><EXPRESSION_STATEMENT-21>					this._onUnresolvableError.fire();
</EXPRESSION_STATEMENT-21><RETURN_STATEMENT-11>					return;
</RETURN_STATEMENT-11>				}
</IF_STATEMENT-5>			} finally {
<EXPRESSION_STATEMENT-22>				clearTimeout(timeoutHandle);
</EXPRESSION_STATEMENT-22>			}
</TRY_STATEMENT-2>		}
</IF_STATEMENT-4><EXPRESSION_STATEMENT-23>
		await chatService.resendRequest(requestModel, { mode, userSelectedModelId: languageModel });
</EXPRESSION_STATEMENT-23>	}
</METHOD_DEFINITION-8><METHOD_DEFINITION-9>
	private whenLanguageModelReady(languageModelsService: ILanguageModelsService): Promise<unknown> | void {
<FOR_IN_STATEMENT>		for (const id of languageModelsService.getLanguageModelIds()) {
<LEXICAL_DECLARATION-23>			const model = languageModelsService.lookupLanguageModel(id);
</LEXICAL_DECLARATION-23><IF_STATEMENT-6>			if (model && model.isDefault) {
<RETURN_STATEMENT-12>				return; // we have language models!
</RETURN_STATEMENT-12>			}
</IF_STATEMENT-6>		}
</FOR_IN_STATEMENT><RETURN_STATEMENT-13>
		return Event.toPromise(Event.filter(languageModelsService.onDidChangeLanguageModels, e => e.added?.some(added => added.metadata.isDefault) ?? false));
</RETURN_STATEMENT-13>	}
</METHOD_DEFINITION-9><METHOD_DEFINITION-10>
	private whenToolsModelReady(languageModelToolsService: ILanguageModelToolsService, requestModel: IChatRequestModel): Promise<unknown> | void {
<LEXICAL_DECLARATION-24>
		const needsToolsModel = requestModel.message.parts.some(part => part instanceof ChatRequestToolPart);
</LEXICAL_DECLARATION-24><IF_STATEMENT-7>		if (!needsToolsModel) {
<RETURN_STATEMENT-14>			return; // No tools in this request, no need to check
</RETURN_STATEMENT-14>		}
</IF_STATEMENT-7><COMMENT-9>
		// check that tools other than setup. and internal tools are registered.
</COMMENT-9><FOR_IN_STATEMENT-1>		for (const tool of languageModelToolsService.getTools()) {
<IF_STATEMENT-8>			if (tool.source.type !== 'internal') {
<RETURN_STATEMENT-15>				return; // we have tools!
</RETURN_STATEMENT-15>			}
</IF_STATEMENT-8>		}
</FOR_IN_STATEMENT-1><RETURN_STATEMENT-16>
		return Event.toPromise(Event.filter(languageModelToolsService.onDidChangeTools, (_) => {
<FOR_IN_STATEMENT-2>			for (const tool of languageModelToolsService.getTools()) {
<IF_STATEMENT-9>				if (tool.source.type !== 'internal') {
<RETURN_STATEMENT-17>					return true; // we have tools!
</RETURN_STATEMENT-17>				}
</IF_STATEMENT-9>			}
</FOR_IN_STATEMENT-2><RETURN_STATEMENT-18>			return false; // no external tools found
</RETURN_STATEMENT-18>		}));
</RETURN_STATEMENT-16>	}
</METHOD_DEFINITION-10><METHOD_DEFINITION-11>
	private whenAgentReady(chatAgentService: IChatAgentService, mode: ChatMode | undefined): Promise<unknown> | void {
<LEXICAL_DECLARATION-25>		const defaultAgent = chatAgentService.getDefaultAgent(this.location, mode);
</LEXICAL_DECLARATION-25><IF_STATEMENT-10>		if (defaultAgent && !defaultAgent.isCore) {
<RETURN_STATEMENT-19>			return; // we have a default agent from an extension!
</RETURN_STATEMENT-19>		}
</IF_STATEMENT-10><RETURN_STATEMENT-20>
		return Event.toPromise(Event.filter(chatAgentService.onDidChangeAgents, () => {
<LEXICAL_DECLARATION-26>			const defaultAgent = chatAgentService.getDefaultAgent(this.location, mode);
</LEXICAL_DECLARATION-26><RETURN_STATEMENT-21>			return Boolean(defaultAgent && !defaultAgent.isCore);
</RETURN_STATEMENT-21>		}));
</RETURN_STATEMENT-20>	}
</METHOD_DEFINITION-11><METHOD_DEFINITION-12>
	private async whenDefaultAgentFailed(chatService: IChatService): Promise<void> {
<RETURN_STATEMENT-22>		return new Promise<void>(resolve => {
<EXPRESSION_STATEMENT-24>			chatService.activateDefaultAgent(this.location).catch(() => resolve());
</EXPRESSION_STATEMENT-24>		});
</RETURN_STATEMENT-22>	}
</METHOD_DEFINITION-12><METHOD_DEFINITION-13>
	private async doInvokeWithSetup(request: IChatAgentRequest, progress: (part: IChatProgress) => void, chatService: IChatService, languageModelsService: ILanguageModelsService, chatWidgetService: IChatWidgetService, chatAgentService: IChatAgentService, languageModelToolsService: ILanguageModelToolsService): Promise<IChatAgentResult> {
<EXPRESSION_STATEMENT-25>		this.telemetryService.publicLog2<WorkbenchActionExecutedEvent, WorkbenchActionExecutedClassification>('workbenchActionExecuted', { id: CHAT_SETUP_ACTION_ID, from: 'chat' });
</EXPRESSION_STATEMENT-25><LEXICAL_DECLARATION-27>
		const requestModel = chatWidgetService.getWidgetBySessionId(request.sessionId)?.viewModel?.model.getRequests().at(-1);
</LEXICAL_DECLARATION-27><LEXICAL_DECLARATION-28>
		const setupListener = Event.runAndSubscribe(this.controller.value.onDidChange, (() => {
<SWITCH_STATEMENT-1>			switch (this.controller.value.step) {
<SWITCH_CASE-4>				case ChatSetupStep.SigningIn:
<EXPRESSION_STATEMENT-26>					progress({
						kind: 'progressMessage',
						content: new MarkdownString(localize('setupChatSignIn2', "Signing in to {0}.", ChatEntitlementRequests.providerId(this.configurationService) === defaultChat.enterpriseProviderId ? defaultChat.enterpriseProviderName : defaultChat.providerName)),
					});
</EXPRESSION_STATEMENT-26><BREAK_STATEMENT-4>					break;</BREAK_STATEMENT-4>
</SWITCH_CASE-4><SWITCH_CASE-5>				case ChatSetupStep.Installing:
<EXPRESSION_STATEMENT-27>					progress({
						kind: 'progressMessage',
						content: new MarkdownString(localize('installingCopilot', "Getting Copilot ready.")),
					});
</EXPRESSION_STATEMENT-27><BREAK_STATEMENT-5>					break;</BREAK_STATEMENT-5>
</SWITCH_CASE-5>			}
</SWITCH_STATEMENT-1>		}));
</LEXICAL_DECLARATION-28><LEXICAL_DECLARATION-29>
		let result: IChatSetupResult | undefined = undefined;
</LEXICAL_DECLARATION-29><TRY_STATEMENT-3>		try {
<EXPRESSION_STATEMENT-28>			result = await ChatSetup.getInstance(this.instantiationService, this.context, this.controller).run();
</EXPRESSION_STATEMENT-28>		} catch (error) {
<EXPRESSION_STATEMENT-29>			this.logService.error(`[chat setup] Error during setup: ${toErrorMessage(error)}`);
</EXPRESSION_STATEMENT-29>		} finally {
<EXPRESSION_STATEMENT-30>			setupListener.dispose();
</EXPRESSION_STATEMENT-30>		}
</TRY_STATEMENT-3><COMMENT-10>
		// User has agreed to run the setup
</COMMENT-10><IF_STATEMENT-11>		if (typeof result?.success === 'boolean') {
<IF_STATEMENT-12>			if (result.success) {
<IF_STATEMENT-13>				if (result.dialogSkipped) {
<EXPRESSION_STATEMENT-31>					progress({
						kind: 'progressMessage',
						content: new MarkdownString(localize('copilotSetupSuccess', "Copilot setup finished successfully."))
					});
</EXPRESSION_STATEMENT-31>				} else if (requestModel) {
<COMMENT-11>					// Replace agent part with the actual Copilot agent
</COMMENT-11><LEXICAL_DECLARATION-30>					let newRequest = this.replaceAgentInRequestModel(requestModel, chatAgentService);
</LEXICAL_DECLARATION-30><COMMENT-12>					// Then replace any tool parts with the actual Copilot tools
</COMMENT-12><EXPRESSION_STATEMENT-32>					newRequest = this.replaceToolInRequestModel(newRequest);
</EXPRESSION_STATEMENT-32><EXPRESSION_STATEMENT-33>					await this.forwardRequestToCopilot(newRequest, progress, chatService, languageModelsService, chatAgentService, chatWidgetService, languageModelToolsService);
</EXPRESSION_STATEMENT-33>				}
</IF_STATEMENT-13>			} else {
<EXPRESSION_STATEMENT-34>				progress({
					kind: 'warning',
					content: new MarkdownString(localize('copilotSetupError', "Copilot setup failed."))
				});
</EXPRESSION_STATEMENT-34>			}
</IF_STATEMENT-12>		}
<COMMENT-13>
		// User has cancelled the setup
</COMMENT-13>		else {
<EXPRESSION_STATEMENT-35>			progress({
				kind: 'markdownContent',
				content: SetupChatAgent.SETUP_NEEDED_MESSAGE,
			});
</EXPRESSION_STATEMENT-35>		}
</IF_STATEMENT-11><RETURN_STATEMENT-23>
		return {};
</RETURN_STATEMENT-23>	}
</METHOD_DEFINITION-13><METHOD_DEFINITION-14>
	private replaceAgentInRequestModel(requestModel: IChatRequestModel, chatAgentService: IChatAgentService): IChatRequestModel {
<LEXICAL_DECLARATION-31>		const agentPart = requestModel.message.parts.find((r): r is ChatRequestAgentPart => r instanceof ChatRequestAgentPart);
</LEXICAL_DECLARATION-31><IF_STATEMENT-14>		if (!agentPart) {
<RETURN_STATEMENT-24>			return requestModel;
</RETURN_STATEMENT-24>		}
</IF_STATEMENT-14><LEXICAL_DECLARATION-32>
		const agentId = agentPart.agent.id.replace(/setup\./, `${defaultChat.extensionId}.`.toLowerCase());
</LEXICAL_DECLARATION-32><LEXICAL_DECLARATION-33>		const githubAgent = chatAgentService.getAgent(agentId);
</LEXICAL_DECLARATION-33><IF_STATEMENT-15>		if (!githubAgent) {
<RETURN_STATEMENT-25>			return requestModel;
</RETURN_STATEMENT-25>		}
</IF_STATEMENT-15><LEXICAL_DECLARATION-34>
		const newAgentPart = new ChatRequestAgentPart(agentPart.range, agentPart.editorRange, githubAgent);
</LEXICAL_DECLARATION-34><RETURN_STATEMENT-26>
		return new ChatRequestModel({
			session: requestModel.session as ChatModel,
			message: {
				parts: requestModel.message.parts.map(part => {
<IF_STATEMENT-16>					if (part instanceof ChatRequestAgentPart) {
<RETURN_STATEMENT-27>						return newAgentPart;
</RETURN_STATEMENT-27>					}
</IF_STATEMENT-16><RETURN_STATEMENT-28>					return part;
</RETURN_STATEMENT-28>				}),
				text: requestModel.message.text
			},
			variableData: requestModel.variableData,
			timestamp: Date.now(),
			attempt: requestModel.attempt,
			confirmation: requestModel.confirmation,
			locationData: requestModel.locationData,
			attachedContext: requestModel.attachedContext,
			isCompleteAddedRequest: requestModel.isCompleteAddedRequest,
		});
</RETURN_STATEMENT-26>	}
</METHOD_DEFINITION-14><METHOD_DEFINITION-15>
	private replaceToolInRequestModel(requestModel: IChatRequestModel): IChatRequestModel {
<LEXICAL_DECLARATION-35>		const toolPart = requestModel.message.parts.find((r): r is ChatRequestToolPart => r instanceof ChatRequestToolPart);
</LEXICAL_DECLARATION-35><IF_STATEMENT-17>		if (!toolPart) {
<RETURN_STATEMENT-29>			return requestModel;
</RETURN_STATEMENT-29>		}
</IF_STATEMENT-17><LEXICAL_DECLARATION-36>
		const toolId = toolPart.toolId.replace(/setup.tools\./, `copilot_`.toLowerCase());
</LEXICAL_DECLARATION-36><LEXICAL_DECLARATION-37>		const newToolPart = new ChatRequestToolPart(
			toolPart.range,
			toolPart.editorRange,
			toolPart.toolName,
			toolId,
			toolPart.displayName,
			toolPart.icon
		);
</LEXICAL_DECLARATION-37><LEXICAL_DECLARATION-38>
		const chatRequestToolEntry: IChatRequestToolEntry = {
			id: toolId,
			name: 'new',
			range: toolPart.range,
			kind: 'tool',
			value: undefined
		};
</LEXICAL_DECLARATION-38><LEXICAL_DECLARATION-39>
		const variableData: IChatRequestVariableData = {
			variables: [chatRequestToolEntry]
		};
</LEXICAL_DECLARATION-39><RETURN_STATEMENT-30>
		return new ChatRequestModel({
			session: requestModel.session as ChatModel,
			message: {
				parts: requestModel.message.parts.map(part => {
<IF_STATEMENT-18>					if (part instanceof ChatRequestToolPart) {
<RETURN_STATEMENT-31>						return newToolPart;
</RETURN_STATEMENT-31>					}
</IF_STATEMENT-18><RETURN_STATEMENT-32>					return part;
</RETURN_STATEMENT-32>				}),
				text: requestModel.message.text
			},
			variableData: variableData,
			timestamp: Date.now(),
			attempt: requestModel.attempt,
			confirmation: requestModel.confirmation,
			locationData: requestModel.locationData,
			attachedContext: [chatRequestToolEntry],
			isCompleteAddedRequest: requestModel.isCompleteAddedRequest,
		});
</RETURN_STATEMENT-30>	}
</METHOD_DEFINITION-15>}
</CLASS_DECLARATION><CLASS_DECLARATION-1>

class SetupTool extends Disposable implements IToolImpl {
<METHOD_DEFINITION-16>
	static registerTools(instantiationService: IInstantiationService, toolData: IToolData): { disposable: IDisposable; tool: SetupTool } {
<RETURN_STATEMENT-33>		return instantiationService.invokeFunction(accessor => {
<LEXICAL_DECLARATION-40>			const disposables = new DisposableStore();
</LEXICAL_DECLARATION-40><LEXICAL_DECLARATION-41>			const toolService = accessor.get(ILanguageModelToolsService);
</LEXICAL_DECLARATION-41><EXPRESSION_STATEMENT-36>			disposables.add(toolService.registerToolData(toolData));
</EXPRESSION_STATEMENT-36><LEXICAL_DECLARATION-42>			const tool = instantiationService.createInstance(SetupTool);
</LEXICAL_DECLARATION-42><EXPRESSION_STATEMENT-37>			disposables.add(toolService.registerToolImplementation(toolData.id, tool));
</EXPRESSION_STATEMENT-37><RETURN_STATEMENT-34>			return { tool, disposable: disposables };
</RETURN_STATEMENT-34>		});
</RETURN_STATEMENT-33>	}
</METHOD_DEFINITION-16><CONSTRUCTOR-1>
	constructor(
	) {
<EXPRESSION_STATEMENT-38>		super();
</EXPRESSION_STATEMENT-38>	}
</CONSTRUCTOR-1><METHOD_DEFINITION-17>
	invoke(invocation: IToolInvocation, countTokens: CountTokensCallback, token: CancellationToken): Promise<IToolResult> {
<LEXICAL_DECLARATION-43>		const result: IToolResult = {
			content: [
				{
					kind: 'text',
					value: ''
				}
			]
		};
</LEXICAL_DECLARATION-43><RETURN_STATEMENT-35>		return Promise.resolve(result);
</RETURN_STATEMENT-35>	}
</METHOD_DEFINITION-17><METHOD_DEFINITION-18>
	prepareToolInvocation?(parameters: any, token: CancellationToken): Promise<IPreparedToolInvocation | undefined> {
<RETURN_STATEMENT-36>		return Promise.resolve(undefined);
</RETURN_STATEMENT-36>	}
</METHOD_DEFINITION-18>}
</CLASS_DECLARATION-1><ENUM_DECLARATION>
enum ChatSetupStrategy {
<ENUM_ASSIGNMENT>	Canceled = 0,
</ENUM_ASSIGNMENT><ENUM_ASSIGNMENT-1>	DefaultSetup = 1,
</ENUM_ASSIGNMENT-1><ENUM_ASSIGNMENT-2>	SetupWithoutEnterpriseProvider = 2,
</ENUM_ASSIGNMENT-2><ENUM_ASSIGNMENT-3>	SetupWithEnterpriseProvider = 3
</ENUM_ASSIGNMENT-3>}
</ENUM_DECLARATION><INTERFACE_DECLARATION>
interface IChatSetupResult {
<PROPERTY_SIGNATURE>	readonly success: boolean | undefined;
</PROPERTY_SIGNATURE><PROPERTY_SIGNATURE-1>	readonly dialogSkipped: boolean;
</PROPERTY_SIGNATURE-1>}
</INTERFACE_DECLARATION><CLASS_DECLARATION-2>
class ChatSetup {
<PUBLIC_FIELD_DEFINITION-4>
	private static instance: ChatSetup | undefined = undefined;
</PUBLIC_FIELD_DEFINITION-4><METHOD_DEFINITION-19>	static getInstance(instantiationService: IInstantiationService, context: ChatEntitlementContext, controller: Lazy<ChatSetupController>): ChatSetup {
<LEXICAL_DECLARATION-44>		let instance = ChatSetup.instance;
</LEXICAL_DECLARATION-44><IF_STATEMENT-19>		if (!instance) {
<EXPRESSION_STATEMENT-39>			instance = ChatSetup.instance = instantiationService.invokeFunction(accessor => {
<RETURN_STATEMENT-37>				return new ChatSetup(context, controller, instantiationService, accessor.get(ITelemetryService), accessor.get(IContextMenuService), accessor.get(IWorkbenchLayoutService), accessor.get(IKeybindingService), accessor.get(IChatEntitlementService), accessor.get(ILogService), accessor.get(IConfigurationService));
</RETURN_STATEMENT-37>			});
</EXPRESSION_STATEMENT-39>		}
</IF_STATEMENT-19><RETURN_STATEMENT-38>
		return instance;
</RETURN_STATEMENT-38>	}
</METHOD_DEFINITION-19><PUBLIC_FIELD_DEFINITION-5>
	private pendingRun: Promise<IChatSetupResult> | undefined = undefined;
</PUBLIC_FIELD_DEFINITION-5><PUBLIC_FIELD_DEFINITION-6>
	private skipDialogOnce = false;
</PUBLIC_FIELD_DEFINITION-6><CONSTRUCTOR-2>
	private constructor(
		private readonly context: ChatEntitlementContext,
		private readonly controller: Lazy<ChatSetupController>,
		@IInstantiationService private readonly instantiationService: IInstantiationService,
		@ITelemetryService private readonly telemetryService: ITelemetryService,
		@IContextMenuService private readonly contextMenuService: IContextMenuService,
		@ILayoutService private readonly layoutService: IWorkbenchLayoutService,
		@IKeybindingService private readonly keybindingService: IKeybindingService,
		@IChatEntitlementService private readonly chatEntitlementService: IChatEntitlementService,
		@ILogService private readonly logService: ILogService,
		@IConfigurationService private readonly configurationService: IConfigurationService
	) { }
</CONSTRUCTOR-2><METHOD_DEFINITION-20>
	skipDialog(): void {
<EXPRESSION_STATEMENT-40>		this.skipDialogOnce = true;
</EXPRESSION_STATEMENT-40>	}
</METHOD_DEFINITION-20><METHOD_DEFINITION-21>
	async run(): Promise<IChatSetupResult> {
<IF_STATEMENT-20>		if (this.pendingRun) {
<RETURN_STATEMENT-39>			return this.pendingRun;
</RETURN_STATEMENT-39>		}
</IF_STATEMENT-20><EXPRESSION_STATEMENT-41>
		this.pendingRun = this.doRun();
</EXPRESSION_STATEMENT-41><TRY_STATEMENT-4>
		try {
<RETURN_STATEMENT-40>			return await this.pendingRun;
</RETURN_STATEMENT-40>		} finally {
<EXPRESSION_STATEMENT-42>			this.pendingRun = undefined;
</EXPRESSION_STATEMENT-42>		}
</TRY_STATEMENT-4>	}
</METHOD_DEFINITION-21><METHOD_DEFINITION-22>
	private async doRun(): Promise<IChatSetupResult> {
<LEXICAL_DECLARATION-45>		const dialogSkipped = this.skipDialogOnce;
</LEXICAL_DECLARATION-45><EXPRESSION_STATEMENT-43>		this.skipDialogOnce = false;
</EXPRESSION_STATEMENT-43><LEXICAL_DECLARATION-46>
		let setupStrategy: ChatSetupStrategy;
</LEXICAL_DECLARATION-46><IF_STATEMENT-21>		if (dialogSkipped || this.chatEntitlementService.entitlement === ChatEntitlement.Pro || this.chatEntitlementService.entitlement === ChatEntitlement.Limited) {
<EXPRESSION_STATEMENT-44>			setupStrategy = ChatSetupStrategy.DefaultSetup; // existing pro/free users setup without a dialog
</EXPRESSION_STATEMENT-44>		} else {
<EXPRESSION_STATEMENT-45>			setupStrategy = await this.showDialog();
</EXPRESSION_STATEMENT-45>		}
</IF_STATEMENT-21><IF_STATEMENT-22>
		if (setupStrategy === ChatSetupStrategy.DefaultSetup && ChatEntitlementRequests.providerId(this.configurationService) === defaultChat.enterpriseProviderId) {
<EXPRESSION_STATEMENT-46>			setupStrategy = ChatSetupStrategy.SetupWithEnterpriseProvider; // users with a configured provider go through provider setup
</EXPRESSION_STATEMENT-46>		}
</IF_STATEMENT-22><LEXICAL_DECLARATION-47>
		let success = undefined;
</LEXICAL_DECLARATION-47><TRY_STATEMENT-5>		try {
<SWITCH_STATEMENT-2>			switch (setupStrategy) {
<SWITCH_CASE-6>				case ChatSetupStrategy.SetupWithEnterpriseProvider:
<EXPRESSION_STATEMENT-47>					success = await this.controller.value.setupWithProvider({ useEnterpriseProvider: true });
</EXPRESSION_STATEMENT-47><BREAK_STATEMENT-6>					break;</BREAK_STATEMENT-6>
</SWITCH_CASE-6><SWITCH_CASE-7>				case ChatSetupStrategy.SetupWithoutEnterpriseProvider:
<EXPRESSION_STATEMENT-48>					success = await this.controller.value.setupWithProvider({ useEnterpriseProvider: false });
</EXPRESSION_STATEMENT-48><BREAK_STATEMENT-7>					break;</BREAK_STATEMENT-7>
</SWITCH_CASE-7><SWITCH_CASE-8>				case ChatSetupStrategy.DefaultSetup:
<EXPRESSION_STATEMENT-49>					success = await this.controller.value.setup();
</EXPRESSION_STATEMENT-49><BREAK_STATEMENT-8>					break;</BREAK_STATEMENT-8>
</SWITCH_CASE-8>			}
</SWITCH_STATEMENT-2>		} catch (error) {
<EXPRESSION_STATEMENT-50>			this.logService.error(`[chat setup] Error during setup: ${toErrorMessage(error)}`);
</EXPRESSION_STATEMENT-50><EXPRESSION_STATEMENT-51>			success = false;
</EXPRESSION_STATEMENT-51>		}
</TRY_STATEMENT-5><RETURN_STATEMENT-41>
		return { success, dialogSkipped };
</RETURN_STATEMENT-41>	}
</METHOD_DEFINITION-22><METHOD_DEFINITION-23>
	private async showDialog(): Promise<ChatSetupStrategy> {
<LEXICAL_DECLARATION-48>		const disposables = new DisposableStore();
</LEXICAL_DECLARATION-48><LEXICAL_DECLARATION-49>
		let result: ChatSetupStrategy | undefined = undefined;
</LEXICAL_DECLARATION-49><LEXICAL_DECLARATION-50>
		const buttons = [this.getPrimaryButton(), localize('maybeLater', "Maybe Later")];
</LEXICAL_DECLARATION-50><LEXICAL_DECLARATION-51>
		const dialog = disposables.add(new Dialog(
			this.layoutService.activeContainer,
			this.getDialogTitle(),
			buttons,
			createWorkbenchDialogOptions({
				type: 'none',
				icon: Codicon.copilotLarge,
				cancelId: buttons.length - 1,
				renderBody: body => body.appendChild(this.createDialog(disposables)),
				primaryButtonDropdown: {
					contextMenuProvider: this.contextMenuService,
					addPrimaryActionToDropdown: false,
					actions: [
						toAction({ id: 'setupWithProvider', label: localize('setupWithProvider', "Sign in with a {0} Account", defaultChat.providerName), run: () => result = ChatSetupStrategy.SetupWithoutEnterpriseProvider }),
						toAction({ id: 'setupWithEnterpriseProvider', label: localize('setupWithEnterpriseProvider', "Sign in with a {0} Account", defaultChat.enterpriseProviderName), run: () => result = ChatSetupStrategy.SetupWithEnterpriseProvider }),
					]
				}
			}, this.keybindingService, this.layoutService)
		));
</LEXICAL_DECLARATION-51><LEXICAL_DECLARATION-52>
		const { button } = await dialog.show();
</LEXICAL_DECLARATION-52><EXPRESSION_STATEMENT-52>		disposables.dispose();
</EXPRESSION_STATEMENT-52><RETURN_STATEMENT-42>
		return button === 0 ? result ?? ChatSetupStrategy.DefaultSetup : ChatSetupStrategy.Canceled;
</RETURN_STATEMENT-42>	}
</METHOD_DEFINITION-23><METHOD_DEFINITION-24>
	private getPrimaryButton(): string {
<IF_STATEMENT-23>		if (this.context.state.entitlement === ChatEntitlement.Unknown) {
<RETURN_STATEMENT-43>			return localize('signInButton', "Sign in");
</RETURN_STATEMENT-43>		}
</IF_STATEMENT-23><RETURN_STATEMENT-44>
		return localize('useCopilotButton', "Use Copilot");
</RETURN_STATEMENT-44>	}
</METHOD_DEFINITION-24><METHOD_DEFINITION-25>
	private getDialogTitle(): string {
<IF_STATEMENT-24>		if (this.context.state.entitlement === ChatEntitlement.Unknown) {
<RETURN_STATEMENT-45>			return this.context.state.registered ? localize('signUp', "Sign in to use Copilot") : localize('signUpFree', "Sign in to use Copilot for free");
</RETURN_STATEMENT-45>		}
</IF_STATEMENT-24><IF_STATEMENT-25>
		if (this.context.state.entitlement === ChatEntitlement.Pro) {
<RETURN_STATEMENT-46>			return localize('copilotProTitle', "Start using Copilot Pro");
</RETURN_STATEMENT-46>		}
</IF_STATEMENT-25><RETURN_STATEMENT-47>
		return this.context.state.registered ? localize('copilotTitle', "Start using Copilot") : localize('copilotFreeTitle', "Start using Copilot for free");
</RETURN_STATEMENT-47>	}
</METHOD_DEFINITION-25><METHOD_DEFINITION-26>
	private createDialog(disposables: DisposableStore): HTMLElement {
<LEXICAL_DECLARATION-53>		const element = $('.chat-setup-dialog');
</LEXICAL_DECLARATION-53><LEXICAL_DECLARATION-54>
		const markdown = this.instantiationService.createInstance(MarkdownRenderer, {});
</LEXICAL_DECLARATION-54><COMMENT-14>
		// Header
</COMMENT-14><LEXICAL_DECLARATION-55>		const header = localize({ key: 'headerDialog', comment: ['{Locked="[Copilot]({0})"}'] }, "[Copilot]({0}) is your AI pair programmer. Write code faster with completions, fix bugs and build new features across multiple files, and learn about your codebase through chat.", defaultChat.documentationUrl);
</LEXICAL_DECLARATION-55><EXPRESSION_STATEMENT-53>		element.appendChild($('p.setup-header', undefined, disposables.add(markdown.render(new MarkdownString(header, { isTrusted: true }))).element));
</EXPRESSION_STATEMENT-53><COMMENT-15>
		// Terms
</COMMENT-15><LEXICAL_DECLARATION-56>		const terms = localize({ key: 'terms', comment: ['{Locked="["}', '{Locked="]({0})"}', '{Locked="]({1})"}'] }, "By continuing, you agree to the [Terms]({0}) and [Privacy Policy]({1}).", defaultChat.termsStatementUrl, defaultChat.privacyStatementUrl);
</LEXICAL_DECLARATION-56><EXPRESSION_STATEMENT-54>		element.appendChild($('p.setup-legal', undefined, disposables.add(markdown.render(new MarkdownString(terms, { isTrusted: true }))).element));
</EXPRESSION_STATEMENT-54><COMMENT-16>
		// SKU Settings
</COMMENT-16><IF_STATEMENT-26>		if (this.telemetryService.telemetryLevel !== TelemetryLevel.NONE) {
<LEXICAL_DECLARATION-57>			const settings = localize({ key: 'settings', comment: ['{Locked="["}', '{Locked="]({0})"}', '{Locked="]({1})"}'] }, "Copilot Free and Pro may show [public code]({0}) suggestions and we may use your data for product improvement. You can change these [settings]({1}) at any time.", defaultChat.publicCodeMatchesUrl, defaultChat.manageSettingsUrl);
</LEXICAL_DECLARATION-57><EXPRESSION_STATEMENT-55>			element.appendChild($('p.setup-settings', undefined, disposables.add(markdown.render(new MarkdownString(settings, { isTrusted: true }))).element));
</EXPRESSION_STATEMENT-55>		}
</IF_STATEMENT-26><RETURN_STATEMENT-48>
		return element;
</RETURN_STATEMENT-48>	}
</METHOD_DEFINITION-26>}
</CLASS_DECLARATION-2><CLASS_DECLARATION-3>
export class ChatSetupContribution extends Disposable implements IWorkbenchContribution {
<PUBLIC_FIELD_DEFINITION-7>
	static readonly ID = 'workbench.contrib.chatSetup';
</PUBLIC_FIELD_DEFINITION-7><CONSTRUCTOR-3>
	constructor(
		@IProductService private readonly productService: IProductService,
		@IInstantiationService private readonly instantiationService: IInstantiationService,
		@ICommandService private readonly commandService: ICommandService,
		@ITelemetryService private readonly telemetryService: ITelemetryService,
		@IChatEntitlementService chatEntitlementService: ChatEntitlementService,
		@ILogService private readonly logService: ILogService,
	) {
<EXPRESSION_STATEMENT-56>		super();
</EXPRESSION_STATEMENT-56><LEXICAL_DECLARATION-58>
		const context = chatEntitlementService.context?.value;
</LEXICAL_DECLARATION-58><LEXICAL_DECLARATION-59>		const requests = chatEntitlementService.requests?.value;
</LEXICAL_DECLARATION-59><IF_STATEMENT-27>		if (!context || !requests) {
<RETURN_STATEMENT-49>			return; // disabled
</RETURN_STATEMENT-49>		}
</IF_STATEMENT-27><LEXICAL_DECLARATION-60>
		const controller = new Lazy(() => this._register(this.instantiationService.createInstance(ChatSetupController, context, requests)));
</LEXICAL_DECLARATION-60><EXPRESSION_STATEMENT-57>
		this.registerSetupAgents(context, controller);
</EXPRESSION_STATEMENT-57><EXPRESSION_STATEMENT-58>		this.registerActions(context, requests, controller);
</EXPRESSION_STATEMENT-58><EXPRESSION_STATEMENT-59>		this.registerUrlLinkHandler();
</EXPRESSION_STATEMENT-59>	}
</CONSTRUCTOR-3><METHOD_DEFINITION-27>
	private registerSetupAgents(context: ChatEntitlementContext, controller: Lazy<ChatSetupController>): void {
<LEXICAL_DECLARATION-61>		const defaultAgentDisposables = markAsSingleton(new MutableDisposable()); // prevents flicker on window reload
</LEXICAL_DECLARATION-61><LEXICAL_DECLARATION-62>		const otherAgentsAndToolsDisposable = markAsSingleton(new MutableDisposable());
</LEXICAL_DECLARATION-62><LEXICAL_DECLARATION-63>		const updateRegistration = () => {
<LEXICAL_DECLARATION-64>			const disabled = context.state.hidden;
</LEXICAL_DECLARATION-64><IF_STATEMENT-28>			if (!disabled) {
<IF_STATEMENT-29>
				if (!defaultAgentDisposables.value) {
<LEXICAL_DECLARATION-65>					const disposables = defaultAgentDisposables.value = new DisposableStore();
</LEXICAL_DECLARATION-65><COMMENT-17>
					// Panel Agents
</COMMENT-17><LEXICAL_DECLARATION-66>					const panelAgentDisposables = disposables.add(new DisposableStore());
</LEXICAL_DECLARATION-66><FOR_IN_STATEMENT-3>					for (const mode of [ChatMode.Ask, ChatMode.Edit, ChatMode.Agent]) {
<LEXICAL_DECLARATION-67>						const { agent, disposable } = SetupChatAgent.registerDefaultAgents(this.instantiationService, ChatAgentLocation.Panel, mode, context, controller);
</LEXICAL_DECLARATION-67><EXPRESSION_STATEMENT-60>						panelAgentDisposables.add(disposable);
</EXPRESSION_STATEMENT-60><EXPRESSION_STATEMENT-61>						panelAgentDisposables.add(agent.onUnresolvableError(() => {
<COMMENT-18>							// An unresolvable error from our agent registrations means that
</COMMENT-18><COMMENT-19>							// Copilot is unhealthy for some reason. We clear our panel
</COMMENT-19><COMMENT-20>							// registration to give Copilot a chance to show a custom message
</COMMENT-20><COMMENT-21>							// to the user from the views and stop pretending as if there was
</COMMENT-21><COMMENT-22>							// a functional agent.
</COMMENT-22><EXPRESSION_STATEMENT-62>							this.logService.error('[chat setup] Unresolvable error from Copilot agent registration, clearing registration.');
</EXPRESSION_STATEMENT-62><EXPRESSION_STATEMENT-63>							panelAgentDisposables.dispose();
</EXPRESSION_STATEMENT-63>						}));
</EXPRESSION_STATEMENT-61>					}
</FOR_IN_STATEMENT-3><COMMENT-23>
					// Inline Agents
</COMMENT-23><EXPRESSION_STATEMENT-64>					disposables.add(SetupChatAgent.registerDefaultAgents(this.instantiationService, ChatAgentLocation.Terminal, undefined, context, controller).disposable);
</EXPRESSION_STATEMENT-64><EXPRESSION_STATEMENT-65>					disposables.add(SetupChatAgent.registerDefaultAgents(this.instantiationService, ChatAgentLocation.Notebook, undefined, context, controller).disposable);
</EXPRESSION_STATEMENT-65><EXPRESSION_STATEMENT-66>					disposables.add(SetupChatAgent.registerDefaultAgents(this.instantiationService, ChatAgentLocation.Editor, undefined, context, controller).disposable);
</EXPRESSION_STATEMENT-66>				}
</IF_STATEMENT-29><IF_STATEMENT-30>
				if (!context.state.installed && !otherAgentsAndToolsDisposable.value) {
<LEXICAL_DECLARATION-68>					const disposables = otherAgentsAndToolsDisposable.value = new DisposableStore();
</LEXICAL_DECLARATION-68><COMMENT-24>					// VSCode Agent
</COMMENT-24><EXPRESSION_STATEMENT-67>					disposables.add(SetupChatAgent.registerOtherAgents(this.instantiationService, 'setup.vscode', 'vscode', false, localize2('vscodeAgentDescription', "Ask questions about VS Code").value, ChatAgentLocation.Panel, undefined, context, controller).disposable);
</EXPRESSION_STATEMENT-67><COMMENT-25>
					// Tools
</COMMENT-25><EXPRESSION_STATEMENT-68>					disposables.add(SetupTool.registerTools(this.instantiationService, {
						id: 'setup.tools.createNewWorkspace',
						source: {
							type: 'internal',
						},
						icon: Codicon.newFolder,
						displayName: localize('setupToolDisplayName', "New Workspace"),
						modelDescription: localize('setupToolsDescription', "Scaffold a new workspace in VS Code"),
						userDescription: localize('setupToolsDescription', "Scaffold a new workspace in VS Code"),
						canBeReferencedInPrompt: true,
						toolReferenceName: 'new',
						when: ContextKeyExpr.true(),
						supportsToolPicker: true,
					}).disposable);
</EXPRESSION_STATEMENT-68>				}
</IF_STATEMENT-30>
			} else {
<IF_STATEMENT-31>				if (defaultAgentDisposables.value) {
<EXPRESSION_STATEMENT-69>					defaultAgentDisposables.clear();
</EXPRESSION_STATEMENT-69>				}
</IF_STATEMENT-31><IF_STATEMENT-32>				if (otherAgentsAndToolsDisposable.value) {
<EXPRESSION_STATEMENT-70>					otherAgentsAndToolsDisposable.clear();
</EXPRESSION_STATEMENT-70>				}
</IF_STATEMENT-32>			}
</IF_STATEMENT-28><IF_STATEMENT-33>			if (context.state.installed && otherAgentsAndToolsDisposable.value) {
<COMMENT-26>				// we need to do this to prevent showing duplicate agent/tool entries in the list
</COMMENT-26><EXPRESSION_STATEMENT-71>				otherAgentsAndToolsDisposable.clear();
</EXPRESSION_STATEMENT-71>			}
</IF_STATEMENT-33>		};
</LEXICAL_DECLARATION-63><EXPRESSION_STATEMENT-72>
		this._register(Event.runAndSubscribe(context.onDidChange, () => updateRegistration()));
</EXPRESSION_STATEMENT-72>	}
</METHOD_DEFINITION-27><METHOD_DEFINITION-28>
	private registerActions(context: ChatEntitlementContext, requests: ChatEntitlementRequests, controller: Lazy<ChatSetupController>): void {
<LEXICAL_DECLARATION-69>		const chatSetupTriggerContext = ContextKeyExpr.or(
			ChatContextKeys.Setup.installed.negate(),
			ChatContextKeys.Entitlement.canSignUp
		);
</LEXICAL_DECLARATION-69><LEXICAL_DECLARATION-70>
		const CHAT_SETUP_ACTION_LABEL = localize2('triggerChatSetup', "Use AI Features with Copilot for free...");
</LEXICAL_DECLARATION-70><CLASS_DECLARATION-4>
		class ChatSetupTriggerAction extends Action2 {
<CONSTRUCTOR-4>
			constructor() {
<EXPRESSION_STATEMENT-73>				super({
					id: CHAT_SETUP_ACTION_ID,
					title: CHAT_SETUP_ACTION_LABEL,
					category: CHAT_CATEGORY,
					f1: true,
					precondition: chatSetupTriggerContext
				});
</EXPRESSION_STATEMENT-73>			}
</CONSTRUCTOR-4><METHOD_DEFINITION-29>
			override async run(accessor: ServicesAccessor, mode: ChatMode): Promise<void> {
<LEXICAL_DECLARATION-71>				const viewsService = accessor.get(IViewsService);
</LEXICAL_DECLARATION-71><LEXICAL_DECLARATION-72>				const layoutService = accessor.get(IWorkbenchLayoutService);
</LEXICAL_DECLARATION-72><LEXICAL_DECLARATION-73>				const instantiationService = accessor.get(IInstantiationService);
</LEXICAL_DECLARATION-73><LEXICAL_DECLARATION-74>				const dialogService = accessor.get(IDialogService);
</LEXICAL_DECLARATION-74><LEXICAL_DECLARATION-75>				const commandService = accessor.get(ICommandService);
</LEXICAL_DECLARATION-75><LEXICAL_DECLARATION-76>				const lifecycleService = accessor.get(ILifecycleService);
</LEXICAL_DECLARATION-76><EXPRESSION_STATEMENT-74>
				await context.update({ hidden: false });
</EXPRESSION_STATEMENT-74><LEXICAL_DECLARATION-77>
				const chatWidgetPromise = showCopilotView(viewsService, layoutService);
</LEXICAL_DECLARATION-77><IF_STATEMENT-34>				if (mode) {
<LEXICAL_DECLARATION-78>					const chatWidget = await chatWidgetPromise;
</LEXICAL_DECLARATION-78><EXPRESSION_STATEMENT-75>					chatWidget?.input.setChatMode(mode);
</EXPRESSION_STATEMENT-75>				}
</IF_STATEMENT-34><LEXICAL_DECLARATION-79>
				const setup = ChatSetup.getInstance(instantiationService, context, controller);
</LEXICAL_DECLARATION-79><LEXICAL_DECLARATION-80>				const { success } = await setup.run();
</LEXICAL_DECLARATION-80><IF_STATEMENT-35>				if (success === false && !lifecycleService.willShutdown) {
<LEXICAL_DECLARATION-81>					const { confirmed } = await dialogService.confirm({
						type: Severity.Error,
						message: localize('setupErrorDialog', "Copilot setup failed. Would you like to try again?"),
						primaryButton: localize('retry', "Retry"),
					});
</LEXICAL_DECLARATION-81><IF_STATEMENT-36>
					if (confirmed) {
<EXPRESSION_STATEMENT-76>						commandService.executeCommand(CHAT_SETUP_ACTION_ID);
</EXPRESSION_STATEMENT-76>					}
</IF_STATEMENT-36>				}
</IF_STATEMENT-35>			}
</METHOD_DEFINITION-29>		}
</CLASS_DECLARATION-4><CLASS_DECLARATION-5>
		class ChatSetupTriggerWithoutDialogAction extends Action2 {
<CONSTRUCTOR-5>
			constructor() {
<EXPRESSION_STATEMENT-77>				super({
					id: 'workbench.action.chat.triggerSetupWithoutDialog',
					title: CHAT_SETUP_ACTION_LABEL,
					precondition: chatSetupTriggerContext
				});
</EXPRESSION_STATEMENT-77>			}
</CONSTRUCTOR-5><METHOD_DEFINITION-30>
			override async run(accessor: ServicesAccessor): Promise<void> {
<LEXICAL_DECLARATION-82>				const viewsService = accessor.get(IViewsService);
</LEXICAL_DECLARATION-82><LEXICAL_DECLARATION-83>				const layoutService = accessor.get(IWorkbenchLayoutService);
</LEXICAL_DECLARATION-83><LEXICAL_DECLARATION-84>				const instantiationService = accessor.get(IInstantiationService);
</LEXICAL_DECLARATION-84><EXPRESSION_STATEMENT-78>
				await context.update({ hidden: false });
</EXPRESSION_STATEMENT-78><LEXICAL_DECLARATION-85>
				const chatWidget = await showCopilotView(viewsService, layoutService);
</LEXICAL_DECLARATION-85><EXPRESSION_STATEMENT-79>				ChatSetup.getInstance(instantiationService, context, controller).skipDialog();
</EXPRESSION_STATEMENT-79><EXPRESSION_STATEMENT-80>				chatWidget?.acceptInput(localize('setupCopilot', "Set up Copilot."));
</EXPRESSION_STATEMENT-80>			}
</METHOD_DEFINITION-30>		}
</CLASS_DECLARATION-5><CLASS_DECLARATION-6>
		class ChatSetupFromAccountsAction extends Action2 {
<CONSTRUCTOR-6>
			constructor() {
<EXPRESSION_STATEMENT-81>				super({
					id: 'workbench.action.chat.triggerSetupFromAccounts',
					title: localize2('triggerChatSetupFromAccounts', "Sign in to use Copilot..."),
					menu: {
						id: MenuId.AccountsContext,
						group: '2_copilot',
						when: ContextKeyExpr.and(
							ChatContextKeys.Setup.hidden.negate(),
							ChatContextKeys.Setup.installed.negate(),
							ChatContextKeys.Entitlement.signedOut
						)
					}
				});
</EXPRESSION_STATEMENT-81>			}
</CONSTRUCTOR-6><METHOD_DEFINITION-31>
			override async run(accessor: ServicesAccessor): Promise<void> {
<LEXICAL_DECLARATION-86>				const commandService = accessor.get(ICommandService);
</LEXICAL_DECLARATION-86><RETURN_STATEMENT-50>				return commandService.executeCommand(CHAT_SETUP_ACTION_ID);
</RETURN_STATEMENT-50>			}
</METHOD_DEFINITION-31>		}
</CLASS_DECLARATION-6><CLASS_DECLARATION-7>
		class ChatSetupHideAction extends Action2 {
<PUBLIC_FIELD_DEFINITION-8>
			static readonly ID = 'workbench.action.chat.hideSetup';
</PUBLIC_FIELD_DEFINITION-8><PUBLIC_FIELD_DEFINITION-9>			static readonly TITLE = localize2('hideChatSetup', "Hide Copilot");
</PUBLIC_FIELD_DEFINITION-9><CONSTRUCTOR-7>
			constructor() {
<EXPRESSION_STATEMENT-82>				super({
					id: ChatSetupHideAction.ID,
					title: ChatSetupHideAction.TITLE,
					f1: true,
					category: CHAT_CATEGORY,
					precondition: ContextKeyExpr.and(ChatContextKeys.Setup.installed.negate(), ChatContextKeys.Setup.hidden.negate()),
					menu: {
						id: MenuId.ChatTitleBarMenu,
						group: 'z_hide',
						order: 1,
						when: ChatContextKeys.Setup.installed.negate()
					}
				});
</EXPRESSION_STATEMENT-82>			}
</CONSTRUCTOR-7><METHOD_DEFINITION-32>
			override async run(accessor: ServicesAccessor): Promise<void> {
<LEXICAL_DECLARATION-87>				const viewsDescriptorService = accessor.get(IViewDescriptorService);
</LEXICAL_DECLARATION-87><LEXICAL_DECLARATION-88>				const layoutService = accessor.get(IWorkbenchLayoutService);
</LEXICAL_DECLARATION-88><LEXICAL_DECLARATION-89>				const dialogService = accessor.get(IDialogService);
</LEXICAL_DECLARATION-89><LEXICAL_DECLARATION-90>
				const { confirmed } = await dialogService.confirm({
					message: localize('hideChatSetupConfirm', "Are you sure you want to hide Copilot?"),
					detail: localize('hideChatSetupDetail', "You can restore Copilot by running the '{0}' command.", CHAT_SETUP_ACTION_LABEL.value),
					primaryButton: localize('hideChatSetupButton', "Hide Copilot")
				});
</LEXICAL_DECLARATION-90><IF_STATEMENT-37>
				if (!confirmed) {
<RETURN_STATEMENT-51>					return;
</RETURN_STATEMENT-51>				}
</IF_STATEMENT-37><LEXICAL_DECLARATION-91>
				const location = viewsDescriptorService.getViewLocationById(ChatViewId);
</LEXICAL_DECLARATION-91><EXPRESSION_STATEMENT-83>
				await context.update({ hidden: true });
</EXPRESSION_STATEMENT-83><IF_STATEMENT-38>
				if (location === ViewContainerLocation.AuxiliaryBar) {
<LEXICAL_DECLARATION-92>					const activeContainers = viewsDescriptorService.getViewContainersByLocation(location).filter(container => viewsDescriptorService.getViewContainerModel(container).activeViewDescriptors.length > 0);
</LEXICAL_DECLARATION-92><IF_STATEMENT-39>					if (activeContainers.length === 0) {
<EXPRESSION_STATEMENT-84>						layoutService.setPartHidden(true, Parts.AUXILIARYBAR_PART); // hide if there are no views in the secondary sidebar
</EXPRESSION_STATEMENT-84>					}
</IF_STATEMENT-39>				}
</IF_STATEMENT-38>			}
</METHOD_DEFINITION-32>		}
</CLASS_DECLARATION-7><LEXICAL_DECLARATION-93>
		const windowFocusListener = this._register(new MutableDisposable());
</LEXICAL_DECLARATION-93><CLASS_DECLARATION-8>		class UpgradePlanAction extends Action2 {
<CONSTRUCTOR-8>			constructor() {
<EXPRESSION_STATEMENT-85>				super({
					id: 'workbench.action.chat.upgradePlan',
					title: localize2('managePlan', "Upgrade to Copilot Pro"),
					category: localize2('chat.category', 'Chat'),
					f1: true,
					precondition: ContextKeyExpr.or(
						ChatContextKeys.Entitlement.canSignUp,
						ChatContextKeys.Entitlement.limited,
					),
					menu: {
						id: MenuId.ChatTitleBarMenu,
						group: 'a_first',
						order: 1,
						when: ContextKeyExpr.and(
							ChatContextKeys.Entitlement.limited,
							ContextKeyExpr.or(
								ChatContextKeys.chatQuotaExceeded,
								ChatContextKeys.completionsQuotaExceeded
							)
						)
					}
				});
</EXPRESSION_STATEMENT-85>			}
</CONSTRUCTOR-8><METHOD_DEFINITION-33>
			override async run(accessor: ServicesAccessor, from?: string): Promise<void> {
<LEXICAL_DECLARATION-94>				const openerService = accessor.get(IOpenerService);
</LEXICAL_DECLARATION-94><LEXICAL_DECLARATION-95>				const hostService = accessor.get(IHostService);
</LEXICAL_DECLARATION-95><LEXICAL_DECLARATION-96>				const commandService = accessor.get(ICommandService);
</LEXICAL_DECLARATION-96><EXPRESSION_STATEMENT-86>
				openerService.open(URI.parse(defaultChat.upgradePlanUrl));
</EXPRESSION_STATEMENT-86><LEXICAL_DECLARATION-97>
				const entitlement = context.state.entitlement;
</LEXICAL_DECLARATION-97><IF_STATEMENT-40>				if (entitlement !== ChatEntitlement.Pro) {
<COMMENT-27>					// If the user is not yet Pro, we listen to window focus to refresh the token
</COMMENT-27><COMMENT-28>					// when the user has come back to the window assuming the user signed up.
</COMMENT-28><EXPRESSION_STATEMENT-87>					windowFocusListener.value = hostService.onDidChangeFocus(focus => this.onWindowFocus(focus, commandService));
</EXPRESSION_STATEMENT-87>				}
</IF_STATEMENT-40>			}
</METHOD_DEFINITION-33><METHOD_DEFINITION-34>
			private async onWindowFocus(focus: boolean, commandService: ICommandService): Promise<void> {
<IF_STATEMENT-41>				if (focus) {
<EXPRESSION_STATEMENT-88>					windowFocusListener.clear();
</EXPRESSION_STATEMENT-88><LEXICAL_DECLARATION-98>
					const entitlements = await requests.forceResolveEntitlement(undefined);
</LEXICAL_DECLARATION-98><IF_STATEMENT-42>					if (entitlements?.entitlement === ChatEntitlement.Pro) {
<EXPRESSION_STATEMENT-89>						refreshTokens(commandService);
</EXPRESSION_STATEMENT-89>					}
</IF_STATEMENT-42>				}
</IF_STATEMENT-41>			}
</METHOD_DEFINITION-34>		}
</CLASS_DECLARATION-8><EXPRESSION_STATEMENT-90>
		registerAction2(ChatSetupTriggerAction);
</EXPRESSION_STATEMENT-90><EXPRESSION_STATEMENT-91>		registerAction2(ChatSetupFromAccountsAction);
</EXPRESSION_STATEMENT-91><EXPRESSION_STATEMENT-92>		registerAction2(ChatSetupTriggerWithoutDialogAction);
</EXPRESSION_STATEMENT-92><EXPRESSION_STATEMENT-93>		registerAction2(ChatSetupHideAction);
</EXPRESSION_STATEMENT-93><EXPRESSION_STATEMENT-94>		registerAction2(UpgradePlanAction);
</EXPRESSION_STATEMENT-94>	}
</METHOD_DEFINITION-28><METHOD_DEFINITION-35>
	private registerUrlLinkHandler(): void {
<EXPRESSION_STATEMENT-95>		this._register(ExtensionUrlHandlerOverrideRegistry.registerHandler({
			canHandleURL: url => {
<RETURN_STATEMENT-52>				return url.scheme === this.productService.urlProtocol && equalsIgnoreCase(url.authority, defaultChat.chatExtensionId);
</RETURN_STATEMENT-52>			},
			handleURL: async url => {
<LEXICAL_DECLARATION-99>				const params = new URLSearchParams(url.query);
</LEXICAL_DECLARATION-99><EXPRESSION_STATEMENT-96>				this.telemetryService.publicLog2<WorkbenchActionExecutedEvent, WorkbenchActionExecutedClassification>('workbenchActionExecuted', { id: CHAT_SETUP_ACTION_ID, from: 'url', detail: params.get('referrer') ?? undefined });
</EXPRESSION_STATEMENT-96><EXPRESSION_STATEMENT-97>
				await this.commandService.executeCommand(CHAT_SETUP_ACTION_ID, validateChatMode(params.get('mode')));
</EXPRESSION_STATEMENT-97><RETURN_STATEMENT-53>
				return true;
</RETURN_STATEMENT-53>			}
		}));
</EXPRESSION_STATEMENT-95>	}
</METHOD_DEFINITION-35>}
</CLASS_DECLARATION-3><COMMENT-29>
//#endregion
</COMMENT-29><COMMENT-30>
//#region Setup Controller
</COMMENT-30><TYPE_ALIAS_DECLARATION>
type InstallChatClassification = {
	owner: 'bpasero';
	comment: 'Provides insight into chat installation.';
	installResult: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Whether the extension was installed successfully, cancelled or failed to install.' };
	installDuration: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The duration it took to install the extension.' };
	signUpErrorCode: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The error code in case of an error signing up.' };
};
</TYPE_ALIAS_DECLARATION><TYPE_ALIAS_DECLARATION-1>type InstallChatEvent = {
	installResult: 'installed' | 'alreadyInstalled' | 'cancelled' | 'failedInstall' | 'failedNotSignedIn' | 'failedSignUp' | 'failedNotTrusted' | 'failedNoSession';
	installDuration: number;
	signUpErrorCode: number | undefined;
};
</TYPE_ALIAS_DECLARATION-1><ENUM_DECLARATION-1>
enum ChatSetupStep {
<ENUM_ASSIGNMENT-4>	Initial = 1,
</ENUM_ASSIGNMENT-4>	SigningIn,
	Installing
}
</ENUM_DECLARATION-1><CLASS_DECLARATION-9>
class ChatSetupController extends Disposable {
<PUBLIC_FIELD_DEFINITION-10>
	private readonly _onDidChange = this._register(new Emitter<void>());
</PUBLIC_FIELD_DEFINITION-10><PUBLIC_FIELD_DEFINITION-11>	readonly onDidChange = this._onDidChange.event;
</PUBLIC_FIELD_DEFINITION-11><PUBLIC_FIELD_DEFINITION-12>
	private _step = ChatSetupStep.Initial;
</PUBLIC_FIELD_DEFINITION-12><METHOD_DEFINITION-36>	get step(): ChatSetupStep {<RETURN_STATEMENT-54> return this._step;</RETURN_STATEMENT-54> }
</METHOD_DEFINITION-36><CONSTRUCTOR-9>
	constructor(
		private readonly context: ChatEntitlementContext,
		private readonly requests: ChatEntitlementRequests,
		@ITelemetryService private readonly telemetryService: ITelemetryService,
		@IAuthenticationService private readonly authenticationService: IAuthenticationService,
		@IExtensionsWorkbenchService private readonly extensionsWorkbenchService: IExtensionsWorkbenchService,
		@IProductService private readonly productService: IProductService,
		@ILogService private readonly logService: ILogService,
		@IProgressService private readonly progressService: IProgressService,
		@IActivityService private readonly activityService: IActivityService,
		@ICommandService private readonly commandService: ICommandService,
		@IWorkspaceTrustRequestService private readonly workspaceTrustRequestService: IWorkspaceTrustRequestService,
		@IDialogService private readonly dialogService: IDialogService,
		@IConfigurationService private readonly configurationService: IConfigurationService,
		@ILifecycleService private readonly lifecycleService: ILifecycleService,
		@IQuickInputService private readonly quickInputService: IQuickInputService,
	) {
<EXPRESSION_STATEMENT-98>		super();
</EXPRESSION_STATEMENT-98><EXPRESSION_STATEMENT-99>
		this.registerListeners();
</EXPRESSION_STATEMENT-99>	}
</CONSTRUCTOR-9><METHOD_DEFINITION-37>
	private registerListeners(): void {
<EXPRESSION_STATEMENT-100>		this._register(this.context.onDidChange(() => this._onDidChange.fire()));
</EXPRESSION_STATEMENT-100>	}
</METHOD_DEFINITION-37><METHOD_DEFINITION-38>
	private setStep(step: ChatSetupStep): void {
<IF_STATEMENT-43>		if (this._step === step) {
<RETURN_STATEMENT-55>			return;
</RETURN_STATEMENT-55>		}
</IF_STATEMENT-43><EXPRESSION_STATEMENT-101>
		this._step = step;
</EXPRESSION_STATEMENT-101><EXPRESSION_STATEMENT-102>		this._onDidChange.fire();
</EXPRESSION_STATEMENT-102>	}
</METHOD_DEFINITION-38><METHOD_DEFINITION-39>
	async setup(options?: { forceSignIn?: boolean }): Promise<boolean> {
<LEXICAL_DECLARATION-100>		const watch = new StopWatch(false);
</LEXICAL_DECLARATION-100><LEXICAL_DECLARATION-101>		const title = localize('setupChatProgress', "Getting Copilot ready...");
</LEXICAL_DECLARATION-101><LEXICAL_DECLARATION-102>		const badge = this.activityService.showViewContainerActivity(CHAT_SIDEBAR_PANEL_ID, {
			badge: new ProgressBadge(() => title),
		});
</LEXICAL_DECLARATION-102><TRY_STATEMENT-6>
		try {
<RETURN_STATEMENT-56>			return await this.progressService.withProgress({
				location: ProgressLocation.Window,
				command: CHAT_OPEN_ACTION_ID,
				title,
			}, () => this.doSetup(options ?? {}, watch));
</RETURN_STATEMENT-56>		} finally {
<EXPRESSION_STATEMENT-103>			badge.dispose();
</EXPRESSION_STATEMENT-103>		}
</TRY_STATEMENT-6>	}
</METHOD_DEFINITION-39><METHOD_DEFINITION-40>
	private async doSetup(options: { forceSignIn?: boolean }, watch: StopWatch): Promise<boolean> {
<EXPRESSION_STATEMENT-104>		this.context.suspend();  // reduces flicker
</EXPRESSION_STATEMENT-104><LEXICAL_DECLARATION-103>
		let success = false;
</LEXICAL_DECLARATION-103><TRY_STATEMENT-7>		try {
<LEXICAL_DECLARATION-104>			const providerId = ChatEntitlementRequests.providerId(this.configurationService);
</LEXICAL_DECLARATION-104><LEXICAL_DECLARATION-105>			let session: AuthenticationSession | undefined;
</LEXICAL_DECLARATION-105><LEXICAL_DECLARATION-106>			let entitlement: ChatEntitlement | undefined;
</LEXICAL_DECLARATION-106><COMMENT-31>
			// Entitlement Unknown or `forceSignIn`: we need to sign-in user
</COMMENT-31><IF_STATEMENT-44>			if (this.context.state.entitlement === ChatEntitlement.Unknown || options.forceSignIn) {
<EXPRESSION_STATEMENT-105>				this.setStep(ChatSetupStep.SigningIn);
</EXPRESSION_STATEMENT-105><LEXICAL_DECLARATION-107>				const result = await this.signIn(providerId);
</LEXICAL_DECLARATION-107><IF_STATEMENT-45>				if (!result.session) {
<EXPRESSION_STATEMENT-106>					this.telemetryService.publicLog2<InstallChatEvent, InstallChatClassification>('commandCenter.chatInstall', { installResult: 'failedNotSignedIn', installDuration: watch.elapsed(), signUpErrorCode: undefined });
</EXPRESSION_STATEMENT-106><RETURN_STATEMENT-57>					return false;
</RETURN_STATEMENT-57>				}
</IF_STATEMENT-45><EXPRESSION_STATEMENT-107>
				session = result.session;
</EXPRESSION_STATEMENT-107><EXPRESSION_STATEMENT-108>				entitlement = result.entitlement;
</EXPRESSION_STATEMENT-108>			}
</IF_STATEMENT-44><LEXICAL_DECLARATION-108>
			const trusted = await this.workspaceTrustRequestService.requestWorkspaceTrust({
				message: localize('copilotWorkspaceTrust', "Copilot is currently only supported in trusted workspaces.")
			});
</LEXICAL_DECLARATION-108><IF_STATEMENT-46>			if (!trusted) {
<EXPRESSION_STATEMENT-109>				this.telemetryService.publicLog2<InstallChatEvent, InstallChatClassification>('commandCenter.chatInstall', { installResult: 'failedNotTrusted', installDuration: watch.elapsed(), signUpErrorCode: undefined });
</EXPRESSION_STATEMENT-109><RETURN_STATEMENT-58>				return false;
</RETURN_STATEMENT-58>			}
</IF_STATEMENT-46><COMMENT-32>
			// Install
</COMMENT-32><EXPRESSION_STATEMENT-110>			this.setStep(ChatSetupStep.Installing);
</EXPRESSION_STATEMENT-110><EXPRESSION_STATEMENT-111>			success = await this.install(session, entitlement ?? this.context.state.entitlement, providerId, watch);
</EXPRESSION_STATEMENT-111>		} finally {
<EXPRESSION_STATEMENT-112>			this.setStep(ChatSetupStep.Initial);
</EXPRESSION_STATEMENT-112><EXPRESSION_STATEMENT-113>			this.context.resume();
</EXPRESSION_STATEMENT-113>		}
</TRY_STATEMENT-7><RETURN_STATEMENT-59>
		return success;
</RETURN_STATEMENT-59>	}
</METHOD_DEFINITION-40><METHOD_DEFINITION-41>
	private async signIn(providerId: string): Promise<{ session: AuthenticationSession | undefined; entitlement: ChatEntitlement | undefined }> {
<LEXICAL_DECLARATION-109>		let session: AuthenticationSession | undefined;
</LEXICAL_DECLARATION-109><LEXICAL_DECLARATION-110>		let entitlements;
</LEXICAL_DECLARATION-110><TRY_STATEMENT-8>		try {
<EXPRESSION_STATEMENT-114>			({ session, entitlements } = await this.requests.signIn());
</EXPRESSION_STATEMENT-114>		} catch (e) {
<EXPRESSION_STATEMENT-115>			this.logService.error(`[chat setup] signIn: error ${e}`);
</EXPRESSION_STATEMENT-115>		}
</TRY_STATEMENT-8><IF_STATEMENT-47>
		if (!session && !this.lifecycleService.willShutdown) {
<LEXICAL_DECLARATION-111>			const { confirmed } = await this.dialogService.confirm({
				type: Severity.Error,
				message: localize('unknownSignInError', "Failed to sign in to {0}. Would you like to try again?", ChatEntitlementRequests.providerId(this.configurationService) === defaultChat.enterpriseProviderId ? defaultChat.enterpriseProviderName : defaultChat.providerName),
				detail: localize('unknownSignInErrorDetail', "You must be signed in to use Copilot."),
				primaryButton: localize('retry', "Retry")
			});
</LEXICAL_DECLARATION-111><IF_STATEMENT-48>
			if (confirmed) {
<RETURN_STATEMENT-60>				return this.signIn(providerId);
</RETURN_STATEMENT-60>			}
</IF_STATEMENT-48>		}
</IF_STATEMENT-47><RETURN_STATEMENT-61>
		return { session, entitlement: entitlements?.entitlement };
</RETURN_STATEMENT-61>	}
</METHOD_DEFINITION-41><METHOD_DEFINITION-42>
	private async install(session: AuthenticationSession | undefined, entitlement: ChatEntitlement, providerId: string, watch: StopWatch): Promise<boolean> {
<LEXICAL_DECLARATION-112>		const wasInstalled = this.context.state.installed;
</LEXICAL_DECLARATION-112><LEXICAL_DECLARATION-113>		let signUpResult: boolean | { errorCode: number } | undefined = undefined;
</LEXICAL_DECLARATION-113><TRY_STATEMENT-9>
		try {
<IF_STATEMENT-49>
			if (
				entitlement !== ChatEntitlement.Limited &&<COMMENT-33>	// User is not signed up to Copilot Free
</COMMENT-33>				entitlement !== ChatEntitlement.Pro &&<COMMENT-34>		// User is not signed up to Copilot Pro
</COMMENT-34>				entitlement !== ChatEntitlement.Unavailable<COMMENT-35>	// User is eligible for Copilot Free
</COMMENT-35>			) {
<IF_STATEMENT-50>				if (!session) {
<TRY_STATEMENT-10>					try {
<EXPRESSION_STATEMENT-116>						session = (await this.authenticationService.getSessions(providerId)).at(0);
</EXPRESSION_STATEMENT-116>					} catch (error) {
<COMMENT-36>						// ignore - errors can throw if a provider is not registered
</COMMENT-36>					}
</TRY_STATEMENT-10><IF_STATEMENT-51>
					if (!session) {
<EXPRESSION_STATEMENT-117>						this.telemetryService.publicLog2<InstallChatEvent, InstallChatClassification>('commandCenter.chatInstall', { installResult: 'failedNoSession', installDuration: watch.elapsed(), signUpErrorCode: undefined });
</EXPRESSION_STATEMENT-117><RETURN_STATEMENT-62>						return false; // unexpected
</RETURN_STATEMENT-62>					}
</IF_STATEMENT-51>				}
</IF_STATEMENT-50><EXPRESSION_STATEMENT-118>
				signUpResult = await this.requests.signUpLimited(session);
</EXPRESSION_STATEMENT-118><IF_STATEMENT-52>
				if (typeof signUpResult !== 'boolean'<COMMENT-37> /* error */</COMMENT-37>) {
<EXPRESSION_STATEMENT-119>					this.telemetryService.publicLog2<InstallChatEvent, InstallChatClassification>('commandCenter.chatInstall', { installResult: 'failedSignUp', installDuration: watch.elapsed(), signUpErrorCode: signUpResult.errorCode });
</EXPRESSION_STATEMENT-119>				}
</IF_STATEMENT-52>			}
</IF_STATEMENT-49><EXPRESSION_STATEMENT-120>
			await this.doInstall();
</EXPRESSION_STATEMENT-120>		} catch (error) {
<EXPRESSION_STATEMENT-121>			this.logService.error(`[chat setup] install: error ${error}`);
</EXPRESSION_STATEMENT-121><EXPRESSION_STATEMENT-122>			this.telemetryService.publicLog2<InstallChatEvent, InstallChatClassification>('commandCenter.chatInstall', { installResult: isCancellationError(error) ? 'cancelled' : 'failedInstall', installDuration: watch.elapsed(), signUpErrorCode: undefined });
</EXPRESSION_STATEMENT-122><RETURN_STATEMENT-63>			return false;
</RETURN_STATEMENT-63>		}
</TRY_STATEMENT-9><IF_STATEMENT-53>
		if (typeof signUpResult === 'boolean') {
<EXPRESSION_STATEMENT-123>			this.telemetryService.publicLog2<InstallChatEvent, InstallChatClassification>('commandCenter.chatInstall', { installResult: wasInstalled && !signUpResult ? 'alreadyInstalled' : 'installed', installDuration: watch.elapsed(), signUpErrorCode: undefined });
</EXPRESSION_STATEMENT-123>		}
</IF_STATEMENT-53><IF_STATEMENT-54>
		if (wasInstalled && signUpResult === true) {
<EXPRESSION_STATEMENT-124>			refreshTokens(this.commandService);
</EXPRESSION_STATEMENT-124>		}
</IF_STATEMENT-54><RETURN_STATEMENT-64>
		return true;
</RETURN_STATEMENT-64>	}
</METHOD_DEFINITION-42><METHOD_DEFINITION-43>
	private async doInstall(): Promise<void> {
<LEXICAL_DECLARATION-114>		let error: Error | undefined;
</LEXICAL_DECLARATION-114><TRY_STATEMENT-11>		try {
<EXPRESSION_STATEMENT-125>			await this.extensionsWorkbenchService.install(defaultChat.extensionId, {
				enable: true,
				isApplicationScoped: true,<COMMENT-38> 	// install into all profiles
</COMMENT-38>				isMachineScoped: false,<COMMENT-39>		// do not ask to sync
</COMMENT-39>				installEverywhere: true,<COMMENT-40>	// install in local and remote
</COMMENT-40>				installPreReleaseVersion: this.productService.quality !== 'stable'
			}, ChatViewId);
</EXPRESSION_STATEMENT-125>		} catch (e) {
<EXPRESSION_STATEMENT-126>			this.logService.error(`[chat setup] install: error ${error}`);
</EXPRESSION_STATEMENT-126><EXPRESSION_STATEMENT-127>			error = e;
</EXPRESSION_STATEMENT-127>		}
</TRY_STATEMENT-11><IF_STATEMENT-55>
		if (error) {
<IF_STATEMENT-56>			if (!this.lifecycleService.willShutdown) {
<LEXICAL_DECLARATION-115>				const { confirmed } = await this.dialogService.confirm({
					type: Severity.Error,
					message: localize('unknownSetupError', "An error occurred while setting up Copilot. Would you like to try again?"),
					detail: error && !isCancellationError(error) ? toErrorMessage(error) : undefined,
					primaryButton: localize('retry', "Retry")
				});
</LEXICAL_DECLARATION-115><IF_STATEMENT-57>
				if (confirmed) {
<RETURN_STATEMENT-65>					return this.doInstall();
</RETURN_STATEMENT-65>				}
</IF_STATEMENT-57>			}
</IF_STATEMENT-56><THROW_STATEMENT-1>
			throw error;
</THROW_STATEMENT-1>		}
</IF_STATEMENT-55>	}
</METHOD_DEFINITION-43><METHOD_DEFINITION-44>
	async setupWithProvider(options: { useEnterpriseProvider: boolean }): Promise<boolean> {
<LEXICAL_DECLARATION-116>		const registry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration);
</LEXICAL_DECLARATION-116><EXPRESSION_STATEMENT-128>		registry.registerConfiguration({
			'id': 'copilot.setup',
			'type': 'object',
			'properties': {
				[defaultChat.completionsAdvancedSetting]: {
					'type': 'object',
					'properties': {
						'authProvider': {
							'type': 'string'
						}
					}
				},
				[defaultChat.providerUriSetting]: {
					'type': 'string'
				}
			}
		});
</EXPRESSION_STATEMENT-128><IF_STATEMENT-58>
		if (options.useEnterpriseProvider) {
<LEXICAL_DECLARATION-117>			const success = await this.handleEnterpriseInstance();
</LEXICAL_DECLARATION-117><IF_STATEMENT-59>			if (!success) {
<RETURN_STATEMENT-66>				return false; // not properly configured, abort
</RETURN_STATEMENT-66>			}
</IF_STATEMENT-59>		}
</IF_STATEMENT-58><LEXICAL_DECLARATION-118>
		let existingAdvancedSetting = this.configurationService.inspect(defaultChat.completionsAdvancedSetting).user?.value;
</LEXICAL_DECLARATION-118><IF_STATEMENT-60>		if (!isObject(existingAdvancedSetting)) {
<EXPRESSION_STATEMENT-129>			existingAdvancedSetting = {};
</EXPRESSION_STATEMENT-129>		}
</IF_STATEMENT-60><IF_STATEMENT-61>
		if (options.useEnterpriseProvider) {
<EXPRESSION_STATEMENT-130>			await this.configurationService.updateValue(`${defaultChat.completionsAdvancedSetting}`, {
				...existingAdvancedSetting,
				'authProvider': defaultChat.enterpriseProviderId
			}, ConfigurationTarget.USER);
</EXPRESSION_STATEMENT-130>		} else {
<EXPRESSION_STATEMENT-131>			await this.configurationService.updateValue(`${defaultChat.completionsAdvancedSetting}`, Object.keys(existingAdvancedSetting).length > 0 ? {
				...existingAdvancedSetting,
				'authProvider': undefined
			} : undefined, ConfigurationTarget.USER);
</EXPRESSION_STATEMENT-131><EXPRESSION_STATEMENT-132>			await this.configurationService.updateValue(defaultChat.providerUriSetting, undefined, ConfigurationTarget.USER);
</EXPRESSION_STATEMENT-132>		}
</IF_STATEMENT-61><RETURN_STATEMENT-67>
		return this.setup({ ...options, forceSignIn: true });
</RETURN_STATEMENT-67>	}
</METHOD_DEFINITION-44><METHOD_DEFINITION-45>
	private async handleEnterpriseInstance(): Promise<boolean<COMMENT-41> /* success */</COMMENT-41>> {
<LEXICAL_DECLARATION-119>		const domainRegEx = /^[a-zA-Z\-_]+$/;
</LEXICAL_DECLARATION-119><LEXICAL_DECLARATION-120>		const fullUriRegEx = /^(https:\/\/)?([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.ghe\.com\/?$/;
</LEXICAL_DECLARATION-120><LEXICAL_DECLARATION-121>
		const uri = this.configurationService.getValue<string>(defaultChat.providerUriSetting);
</LEXICAL_DECLARATION-121><IF_STATEMENT-62>		if (typeof uri === 'string' && fullUriRegEx.test(uri)) {
<RETURN_STATEMENT-68>			return true; // already setup with a valid URI
</RETURN_STATEMENT-68>		}
</IF_STATEMENT-62><LEXICAL_DECLARATION-122>
		let isSingleWord = false;
</LEXICAL_DECLARATION-122><LEXICAL_DECLARATION-123>		const result = await this.quickInputService.input({
			prompt: localize('enterpriseInstance', "What is your {0} instance?", defaultChat.enterpriseProviderName),
			placeHolder: localize('enterpriseInstancePlaceholder', 'i.e. "octocat" or "https://octocat.ghe.com"...'),
			ignoreFocusLost: true,
			value: uri,
			validateInput: async value => {
<EXPRESSION_STATEMENT-133>				isSingleWord = false;
</EXPRESSION_STATEMENT-133><IF_STATEMENT-63>				if (!value) {
<RETURN_STATEMENT-69>					return undefined;
</RETURN_STATEMENT-69>				}
</IF_STATEMENT-63><IF_STATEMENT-64>
				if (domainRegEx.test(value)) {
<EXPRESSION_STATEMENT-134>					isSingleWord = true;
</EXPRESSION_STATEMENT-134><RETURN_STATEMENT-70>					return {
						content: localize('willResolveTo', "Will resolve to {0}", `https://${value}.ghe.com`),
						severity: Severity.Info
					};
</RETURN_STATEMENT-70>				}</IF_STATEMENT-64><IF_STATEMENT-65> if (!fullUriRegEx.test(value)) {
<RETURN_STATEMENT-71>					return {
						content: localize('invalidEnterpriseInstance', 'You must enter a valid {0} instance (i.e. "octocat" or "https://octocat.ghe.com")', defaultChat.enterpriseProviderName),
						severity: Severity.Error
					};
</RETURN_STATEMENT-71>				}
</IF_STATEMENT-65><RETURN_STATEMENT-72>
				return undefined;
</RETURN_STATEMENT-72>			}
		});
</LEXICAL_DECLARATION-123><IF_STATEMENT-66>
		if (!result) {
<LEXICAL_DECLARATION-124>			const { confirmed } = await this.dialogService.confirm({
				type: Severity.Error,
				message: localize('enterpriseSetupError', "The provided {0} instance is invalid. Would you like to enter it again?", defaultChat.enterpriseProviderName),
				primaryButton: localize('retry', "Retry")
			});
</LEXICAL_DECLARATION-124><IF_STATEMENT-67>
			if (confirmed) {
<RETURN_STATEMENT-73>				return this.handleEnterpriseInstance();
</RETURN_STATEMENT-73>			}
</IF_STATEMENT-67><RETURN_STATEMENT-74>
			return false;
</RETURN_STATEMENT-74>		}
</IF_STATEMENT-66><LEXICAL_DECLARATION-125>
		let resolvedUri = result;
</LEXICAL_DECLARATION-125><IF_STATEMENT-68>		if (isSingleWord) {
<EXPRESSION_STATEMENT-135>			resolvedUri = `https://${resolvedUri}.ghe.com`;
</EXPRESSION_STATEMENT-135>		} else {
<LEXICAL_DECLARATION-126>			const normalizedUri = result.toLowerCase();
</LEXICAL_DECLARATION-126><LEXICAL_DECLARATION-127>			const hasHttps = normalizedUri.startsWith('https://');
</LEXICAL_DECLARATION-127><IF_STATEMENT-69>			if (!hasHttps) {
<EXPRESSION_STATEMENT-136>				resolvedUri = `https://${result}`;
</EXPRESSION_STATEMENT-136>			}
</IF_STATEMENT-69>		}
</IF_STATEMENT-68><EXPRESSION_STATEMENT-137>
		await this.configurationService.updateValue(defaultChat.providerUriSetting, resolvedUri, ConfigurationTarget.USER);
</EXPRESSION_STATEMENT-137><RETURN_STATEMENT-75>
		return true;
</RETURN_STATEMENT-75>	}
</METHOD_DEFINITION-45>}
</CLASS_DECLARATION-9><COMMENT-42>
//#endregion
</COMMENT-42><FUNCTION_DECLARATION>
function refreshTokens(commandService: ICommandService): void {
<COMMENT-43>	// ugly, but we need to signal to the extension that entitlements changed
</COMMENT-43><EXPRESSION_STATEMENT-138>	commandService.executeCommand(defaultChat.completionsRefreshTokenCommand);
</EXPRESSION_STATEMENT-138><EXPRESSION_STATEMENT-139>	commandService.executeCommand(defaultChat.chatRefreshTokenCommand);
</EXPRESSION_STATEMENT-139>}</FUNCTION_DECLARATION>
